Java synchronized

synchronized關鍵字事實上,synchronized修飾非靜態方法、同步代碼塊的synchronized (this)用法和synchronized (非this對象)的用法鎖D的是對象,線程想要執行對應同步代碼,需要獲得對象鎖。

synchronized修飾非靜態方法以及同步代碼塊的synchronized (類.class)用法鎖的是類,線程想要執行對應同步代碼,需要獲得類鎖。

1、對象方法鎖我們先看看非線程安全實例(Run.java):

HasSelfPrivateNum numRef = new HasSelfPrivateNum();

ThreadA athread = new ThreadA(numRef);
athread.start();

ThreadB bthread = new ThreadB(numRef);
bthread.start();

實驗結論:兩個線程訪問同一個對象中的同步方法是一定是線程安全的。
這裏線程獲取的是HasSelfPrivateNum的對象實例的鎖——對象鎖。

HasSelfPrivateNum numRef1 = new HasSelfPrivateNum();
HasSelfPrivateNum numRef2 = new HasSelfPrivateNum();

ThreadA athread = new ThreadA(numRef1);
athread.start();

ThreadB bthread = new ThreadB(numRef2);
bthread.start();

這裏是非同步的,因爲線程athread獲得是numRef1的對象鎖,而bthread線程獲取的是numRef2的對象鎖,他們並沒有在獲取鎖上有競爭關係。
因此,出現非同步的結果。

2、同步塊synchronized (this)
這樣也是同步的,線程獲取的是同步塊synchronized (this)括號()裏面的對象實例的對象鎖,這裏就是ObjectService實例對象的對象鎖了。

需要注意的是synchronized (){}的{}前後的代碼依舊是異步的。
3、synchronized (非this對象)
這裏線程爭奪的是synchronized把持的對象鎖,兩個線程有競爭同一對象鎖的關係,出現同步

現在有一個問題:一個類裏面有兩個非靜態同步方法,會有影響麼?

答案是:如果對象實例A,線程1獲得了對象A的對象鎖,那麼其他線程就不能進入需要獲得對象實例A的對象鎖才能訪問的同步代碼(包括同步方法和同步塊)。不理解可以細細品味一下!
4、靜態synchronized同步方法
兩個線程在爭奪同一個類鎖,因此同步。
5、synchronized (class)
兩個線程依舊在爭奪同一個類鎖,因此同步

需要特別說明:對於同一個類A,線程1爭奪A對象實例的對象鎖,線程2爭奪類A的類鎖,這兩者不存在競爭關係。也就說對象鎖和類鎖互補干預內政

靜態方法則一定會同步,非靜態方法需在單例模式才生效,但是也不能都用靜態同步方法,總之用得不好可能會給性能帶來極大的影響。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章