1. 程式人生 > >單例模式之線程安全問題

單例模式之線程安全問題

進入 解決 變量 實例 pac 單例模式 code 判斷 題解

不考慮線程安全問題的時候單例模式的代碼:

 1 class Bank {
 2     //把該類的構造器聲明為私有
 3     private Bank() {
 4 
 5     }
 6     //設置私有化靜態類變量
 7     private static Bank instance = null;
 8 
 9     //設置獲取該實例的靜態方法
10     public static Bank getInstance() {
11            if (instance == null) {
12                     instance = new
Bank(); 13 } 14 return instance; 15 } 16 }

分析:

  單例模式通俗來說就是要求我們在創建某一個對象的時候只能創建一個這個類的對象。在多線程的情況下,可能會有多個線程在各自的run()方法中調用public static Bank getInstance()方法創建類的對象實例,如果有一個線程再調用方法且未執行完畢的時候發生阻塞,那麽另外一個線程也會執行這個方法,這個時候就會有兩個線程同時創建對象實例,這就違背了單例模式的初中,顯然這樣是線程不安全的,因此我們需要針對這個問題解決線程安全問題。

解決辦法:

  在單例模式中我們可以把instance這個對象實例看成是一個共享數據,我們需要使用同步代碼快或者是同步方法來解決共享數據的線程安全問題。

 1 package com.baozi.java;
 2 
 3 public class BankTest {
 4     //.......
 5 }
 6 /**
 7  * 這是一個單例模式的類:
 8  * 線程安全問題的分析:在多線程的情況下這個單例模式是非線程安全的,多線程的時候會有多個線程通過
 9  * public static Bank getInstance()方法來獲取對象實例,如果某一個線程在進行判斷對象實例是否已經被初始化的時候
10 *對象實例為空,緊接著會進入if()內進行創建對象實例的過程,如果在此時發生阻塞,那麽下一個線程搶占到cpu執行權, 11 * 這時該線程也會進行判斷且對象實例也為空同樣要進去執行創建對象實例的操作,這樣兩個實例都要進行創建對象 12 * 實例,此時是會出現線程安全問題的。 13 *線程安全問題的解決:我們可以使用synchronized代碼塊或者synchronized方法來解決線程安全問題。 14 * 1、如果使用synchronized方法來解決線程安全問題: 15 * public static synchronized Bank getInstance() { 16 * if (instance == null) { 17 * instance = new Bank(); 18 * } 19 * return instance; 20 * } 21 * 2、如果使用synchronized代碼塊來解決線程安全問題: 22 * public static Bank getInstance() { 23 * synchronized (Bank.class) { 24 * if (instance == null) { 25 * instance = new Bank(); 26 * } 27 * return instance; 28 * } 29 * } 30 * 或者是:這種方法效率要比上面全部放在synchronized代碼塊中的效率要高 31 * public static Bank getInstance() { 32 * if(instance == null){ 33 * synchronized (Bank.class) { 34 * if (instance == null) { 35 * instance = new Bank(); 36 * } 37 * } 38 * } 39 * return instance; 40 * } 41 */ 42 class Bank { 43 //把該類的構造器聲明為私有 44 private Bank() { 45 46 } 47 //設置私有化靜態類變量 48 private static Bank instance = null; 49 50 //設置獲取該實例的靜態方法 51 public static Bank getInstance() { 52 if(instance == null){ 53 synchronized (Bank.class) { 54 if (instance == null) { 55 instance = new Bank(); 56 } 57 } 58 } 59 return instance; 60 } 61 }

單例模式之線程安全問題