天天看點

Java多線程之synchronized詳解synchronized作用靜态同步方法非靜态同步方法同步代碼塊

synchronized作用

關鍵字synchronized可以修飾方法或者以同步塊的形式來進行使用,它主要確定多個線程在同一個時刻,隻能有一個線程處于方法或者同步塊中,它保證了線程對變量通路的可見性和排他性,又稱為内置鎖機制。

synchronized的類鎖和對象鎖,本質上是兩把鎖,類鎖實際鎖的是每一個類的class對象。對象鎖鎖的是目前對象執行個體。每個鎖對象都有兩個隊列,一個是就緒隊列,一個是阻塞隊列。就緒隊列存儲了将要獲得鎖的線程,阻塞隊列存儲了被阻塞的線程。一個線程被喚醒後才會進入就緒隊列,等待CPU排程。

在JDK1.5及之前的版本中,synchronized關鍵字加鎖的性能開銷比較大,往往推薦使用原子類。但是在JDK1.6及其之後的版本中,synchronized的性能大大提升。

synchronized具有如下特點:

  • synchronized支援可重入。即A線程調用同步方法method1後,method1内部還調用了同步方法method2,。如果不支援可重入的話,就會造成死鎖。
  • synchronized在擷取鎖後,如果出現異常,會自動釋放鎖
  • 如果子類重寫了父類的同步方法,則該同步是不會繼承的,必須在子類中重新定義synchronized
  • synchronized修飾靜态方法,擷取的鎖是類class鎖,如果有多個執行個體對象,且多個線程通路這些不同執行個體對象的synchronized靜态方法時,仍為同步狀态
  • synchronized靜态方法和synchronized(Object.class)的作用一緻
  • JVM中String具有常量池緩存的功能,即String a="AA"和String b="AA"是相同對象的,是以synchronized(字元串)是同步調用的,不過這種用法比較少】

靜态同步方法

同一個類中所有被synchronized修飾的靜态方法,它們在類範圍内是同步的,即同一時間内隻能有一個線程可以調用它們中的任意一個方法。如果有第二個線程調用其中的任何一個方法,那麼這個線程将挂起,直到前面的線程執行完同步靜态方法後,才會再次被喚醒,執行相應的靜态方法。

不同類中的靜态同步方法互不影響。

java平台會給類配置設定一個類鎖,每個線程通路該類時,會觀察類鎖是否釋放

非靜态同步方法

同一個類中的所有被synchronized修飾的非靜态方法,它們在同一個對象上是同步的。即對于這個類的某個對象,當一個線程調用某個同步方法的時候,如果有第二個線程在同一個對象上調用某個同步的非靜态方法,那這個線程會被挂起。

在不同對象上通路非靜态同步方法不受同步限制。

java平台會給每個對象配置設定對應的對象鎖,每個線程通路該對象時,會觀察對象鎖是否釋放。

同步代碼塊

同步代碼塊可以使用在任何方法中,作用與同步方法類似。

對于同步代碼塊中的代碼,将以括号中的引用所指向的對象為機關進行同步。即如果有多個線程同時通路同步代碼塊,而且同步代碼塊中對象的引用又是指向同一個對象的,那麼就隻有一個線程能夠進入代碼塊執行。

文法如下:

synchronized(對象的引用) {
    同步代碼
}
           

多個線程調用同步代碼塊的時候,必須保證多個線程看到的對象是同一個,即括号中代表的是同一個對象,否則同步無效

同步方法的本質:在多線程環境下,保證關鍵變量是由某個線程獨享的