29
技術社區[雲棲]
哪個對象才是鎖?
我們都知道當一個線程試圖訪問同步代碼塊時,它首先必須得到鎖,退出或拋出異常時必須釋放鎖。這些基礎也許大家都知道,但是很多人還是搞不清哪個對象才是鎖?如果你能正確回答以下問題,那麼才算你徹底搞明白了哪個對象才是鎖?
靜態同步方法問題
如下代碼是兩個靜態同步方法
Class A{
public static synchronized void write(boolean b){
isTrue = b;
}
public static synchronized boolean read(){
return isTrue;
}
}
那麼我們來問幾個問題
- 線程1訪問A.write(true)方法時,線程2能訪問A.read()方法嗎?
- 線程1訪問new A().write(false)方法時,線程2能訪問new A().read()方法嗎?
- 線程1訪問A.write(false)方法時,線程2能訪問new A().read()方法嗎?
實例同步方法問題
如下代碼是兩個實例同步方法
public synchronized void write(boolean b){
isTrue = b;
}
public synchronized boolean read(){
return isTrue;
}
同樣問兩個問題:
- A a=new A(); 線程1訪問a.write(false)方法,線程2能訪問a.read()方法嗎?
- A a=new A(); A b=new A();線程1訪問a.write(false)方法,線程2能訪問b.read()方法嗎?
回答問題之前,先想一下當前方法使用的鎖是哪一個?當前線程是否有拿到這把鎖?拿到鎖了就能訪問當前方法了。
答案
我們先回顧基礎知識,Java中的每一個對象都可以作為鎖,而不同的場景鎖是不一樣的。
- 對於實例同步方法,鎖是當前實例對象。
- 對於靜態同步方法,鎖是當前對象的Class對象。
- 對於同步方法塊,鎖是Synchonized括號裏配置的對象。
線程1訪問A.write()方法時,線程2能訪問A.read()方法嗎?不能,因為靜態方法的鎖都是A.Class對象,線程1拿到鎖之後,線程2就拿不到鎖了。
線程1訪問new A().write()方法時,線程2能訪問new A().read()方法嗎?不能,原因同上。
線程1訪問A.write()方法時,線程2能訪問new A().read()方法嗎?不能,原因同上
A a=new A(); 線程1訪問a.write()方法,線程2能訪問a.read()方法嗎?不能,因為這兩個方法的鎖都是對象a,線程1拿到了鎖,線程2就不能訪問了。
A a=new A(); A b=new A();線程1訪問a.write()方法,線程2能訪問b.read()方法嗎?可以,因為線程1拿到的是鎖是 a,而線程2訪問b.read()需要的是鎖是b。
現在你應該明白了這句話,對於實例同步方法,鎖是當前實例對象。對於靜態同步方法,鎖是當前對象的Class對象。
文章轉自 並發編程網-ifeve.com
最後更新:2017-05-23 11:02:49