在單例模式的懶漢模式中,getinstance方法通常是採用如下方式寫的:
public static stest getinstance()
return stest;
}
這樣的寫法在多執行緒的情況下有可能造成不同的執行緒都例項化了乙個物件出來,所以該寫法是執行緒不安全的。那麼怎麼辦呢?
首先,自然想到既然執行緒不安全的原因是多個執行緒可能同時執行方法,那麼加鎖肯定是乙個不錯的解決方案,
public static synchronized stest getinstance2()
return stest;
}
這樣在一定程度上的確能保證多執行緒下的安全,但是如果多個執行緒都要呼叫該方法,然後都要等待排在前面的執行緒去判斷stest
物件是否為空,在效率上落了下乘。所以為了兼顧安全和效率,有了雙重判否的解決方式。
雙重判否並不是每次進入getinstance方法都需要同步,而是先不同步,進入方法過後,先檢查例項是否存在,如果不存在才進入下面的同步塊,這是第一重檢查。進入同步塊後,再次檢查例項是否存在,如果不存在,就在同步的情況下建立乙個例項,這是第二重檢查。這樣一來,就只需要同步一次了,從而減少了多次在同步情況下進行判斷所浪費的時間。
雙重檢查加鎖機制的實現會使用乙個關鍵字volatile,它的意思是:被volatile修飾的變數的值,將不會被本地執行緒快取,所有對該變數的讀寫都是直接操作共享記憶體,從而確保多個執行緒能正確的處理該變數。
package test0328;
/** * created by cesar on 2016/3/28.
*/public class stest
/*** 這是普通模式
** @return
*/public static stest getinstance()
return stest;
}/**
* 這是同步模式
** @return
*/public static synchronized stest getinstance2()
return stest;
}/**
* 這是雙重判否模式
** @return
*/public static stest getinstance1() }}
return stest;
}}
雙重檢測單例模式
在多執行緒場景下,當乙個執行緒判斷instance為null時 他會新建乙個例項,那麼問題來了,當a執行緒發現物件例項為空時,準備 新建乙個例項,這時cpu輪詢到b執行緒,b執行緒也察覺物件例項為空,它也會新建乙個例項,這樣就破壞了單例模式。首先物件例項必須是全域性共享的,用volatile修飾,然...
單例模式的雙重檢查
單例模式 public class singleton public static singleton getinstance return uniqueinstance 其中有兩次判斷是否為空的語句,第一次是為了提高效率,避免每次都要執行同步 塊,第二次判空,是為了避免多執行緒帶來的不安全,當兩個...
單例模式之雙重檢查
在實現單例模式時,如果未考慮多執行緒的情況,就容易寫出下面的錯誤 public class singleton public singleton getinstance return uniquesingleton 在多執行緒的情況下,這樣寫可能會導致uniquesingleton有多個例項。比如下...