【JAVA】synchronized關鍵字

最近重新梳理了下java的synchronized相關內容,希望能幫助到有需要的朋友們。

主要闡述以下幾個問題:

1.非static方法前加synchronized

class Demo{
     synchronized public void doXXX(){
        //code…
     }
 }

對於這段代碼,我們要考慮這幾個問題:

  1. 理解synchronized鎖的是什麼?
  2. 如果三個線程裏分別new了三個Demo對象,各自的run方法裏分別執行各自Demo對象的doXXX方法,那麼synchronized還起作用嗎?
  3. 如果三個線程裏共用一個Demo對象,各自的run方法裏分別執行這個共用Demo對象的doXXX方法,那麼synchronized還起作用嗎?

在非static方法前面加synchronized,鎖的是這個new出來的Demo對象的本身,也就是this。要執行doXXX方法,必須要先獲取對象鎖(即對象本身)。

所以,2中doXXX的對象鎖來自3個不同的Demo對象,各自線程使用各自Demo對象的鎖,不存在共用鎖的情況,synchronized不起作用。

同理,3中doXXX的對象鎖來自1個相同的Demo對象,各自線程使用同個Demo對象的鎖,存在共用鎖的情況,synchronized起作用。

 

2.方法內部synchronized同步塊

class Demo {
    public void doXXX(){
        synchronized(this){
            //code…
        }
    }
}


對於這段代碼,我們需要考慮這幾個問題:

  1. 括號裏填this?
  2. 括號裏填類.class?
  3. 括號裏填一個對象?

synchronized鎖住的是括號裏的對象,而不是代碼。所以多線程情況下要執行doXXX,要先獲得鎖,即括號裏指定的內容。

分析:

  1. 如果填this,多線程共用同一個Demo對象時,可以控制併發操作帶來的問題,如果各個線程使用各自的Demo對象時,是沒有用的。
  2. 如果填類.class,相當於對類加鎖,也就是在該類的所有成員間實現互斥,在同一時間只有一個線程可訪問該類的實例(如果需要在線程間相互喚醒就需要藉助Object類的wait()方法及nofity()方法),這種方法,不管各個線程使用同一個Demo對象還是使用各自的Demo對象,都可以解決併發操作帶來的問題。一般用方法所在類.class或者方法所在類內部定義一個static的對象,作爲鎖。這種方式稱爲全局鎖。
  3. 對象的情況有很多,可以來自Demo類內部(static和非static),外部傳入(static和非static),但是要傳哪種,相信你看完上面兩條分析,心裏應該有數了。

 

3.static方法前加synchronized

class Demo{
     public static synchronized void doXXX{
         //code…
     }
}


static的synchronized方法,所以它鎖的不是this,而是類的Class對象,而且方法中無法使用this。可見,這種方式不管new幾個Deom調用doXXX,都不會併發。

 

相信你理解了上面三個問題,那麼你對synchronized關鍵字就有了一定的瞭解,並能夠將它運用在處理併發操作的問題上了。

 

 

 

-----------------------------------------------------

請尊重作者勞動成果,

轉載請註明出處

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