天天看點

(49)靜态同步函數的鎖是Class對象,例子:懶漢式--在多線程中存在問題--同步解決

一、如果同步函數被靜态修飾後,使用的鎖是什麼呢?

通過驗證,發現使用的不是this.因為靜态方法中也不可以定義this

靜态進記憶體,記憶體中沒有本類對象,但是一定個該類對應的位元組碼檔案對象。

類名.class 該對象的類型為Class.

靜态的同步方法,使用的鎖是該方法所在類的位元組碼檔案兌現,類名.class

二、懶漢式—-在多線程中存在安全問題

這個靜态方法被run調用後,存在安全問題原因:

s是個共享資料,當一個線程執行到if(s==null)時,判為真時,cpu執行其他的程式去了,比如此時另一個線程,此時執行if(s==null),因為剛才的線程并沒有建立對象,是以判斷為真,這樣就會建立兩個對象,存在安全問題

将此函數改為同步函數,就可以解決這個問題。

class Single

{

private static Single s=null;

private Single(){}

public static synchronized Single getInstance(){

if(s==null)

s=new Single();

return s;

}

但是這樣會使得多線程運作效率低,原因是加鎖多個判斷條件。

為什麼在synchronized中也要寫個if(s==null)呢?

舉個栗子說明:

第一個線程在外層if判斷成功後,進入同步塊,判斷内部的if,成立,此次CPU被剝奪,比如執行到第二個線程,同樣判斷外層的if,因為上同步塊上着鎖,進不了,隔一段時間,第一個線程得到cpu,繼續執行,建立了對象,開鎖。然後隔一段時間,第二個線程繼續執行,進入共享區,然後if(s==null)判斷失敗,開鎖,這就防止了建立對個對象。因為隻有一個對象,是以以後的外層if (s==null)

都判斷失敗,因為已經有對象了,這樣就擺脫了在多線程中使用同步方法、,每次都判斷是否有鎖,運作效率有所提高。

繼續閱讀