1. 程式人生 > >Java中的Synchronized關鍵字用法

Java中的Synchronized關鍵字用法

認識synchronized

對於寫多執行緒程式的人來說,經常碰到的就是併發問題,對於容易出現併發問題的地方加上synchronized修飾符基本上就搞定 了,如果說不考慮效能問題的話,這一招絕對能應對百分之九十以上的情況,若對於效能方面有要求的話就需要額外的知識比如讀寫鎖等等。本文目的先了解透徹synchronized的基本原理。

Synchronized的基本使用

Synchronized的作用主要有三個: 
(1)確保執行緒互斥的訪問同步程式碼 
(2)保證共享變數的修改能夠及時可見 
(3)有效解決重排序問題。 
從語法上講,Synchronized總共有三種用法: 
      (1)修飾普通方法 
    (2)修飾靜態方法 
    (3)修飾程式碼塊 
  

package com.paddx.test.concurrent;
public class SynchronizedDemo {
   public void method() {
       synchronized (this) {
           System.out.println("Method 1 start");
       }
   }
}

對於上述方法我們很容易就知道是執行緒安全的,具體是怎麼做的到的執行緒安全呢,對class通過javap編譯結果如下:

monitorenter

每個物件有一個監視器鎖(monitor)。當monitor被佔用時就會處於鎖定狀態,執行緒執行monitorenter指令時嘗試獲取monitor的所有權,過程如下:

1、如果monitor的進入數為0,則該執行緒進入monitor,然後將進入數設定為1,該執行緒即為monitor的所有者。

2、如果執行緒已經佔有該monitor,只是重新進入,則進入monitor的進入數加1.

3.如果其他執行緒已經佔用了monitor,則該執行緒進入阻塞狀態,直到monitor的進入數為0,再重新嘗試獲取monitor的所有權。

monitorexit

執行monitorexit的執行緒必須是objectref所對應的monitor的所有者。

指令執行時,monitor的進入數減1,如果減1後進入數為0,那執行緒退出monitor,不再是這個monitor的所有者。其他被這個monitor阻塞的執行緒可以嘗試去獲取這個 monitor 的所有權。 
  通過這兩段描述,我們應該能很清楚的看出Synchronized的實現原理,Synchronized的語義底層是通過一個monitor的物件來完成,其實wait/notify等方法也依賴於monitor物件,這就是為什麼只有在同步的塊或者方法中才能呼叫wait/notify等方法,否則會丟擲java.lang.IllegalMonitorStateException的異常的原因。

原理總結

每個物件都有一個內部的鎖或者叫做是監視器,稱之為monitor,當一個方法加上synchronized關鍵字的時候,如果一個執行緒想執行這個方法那麼首先需要獲取這個物件的monirot許可權,對應到指令上面也就是需要獲取monitorenter 指令,如果一個物件獲取到這個指令之後,那麼monitor的進入數為1,當其他執行緒再次獲取的時候發現這個物件的monitor物件被別的執行緒所佔用,那麼進入阻塞狀態,知道佔用這個物件的執行緒執行monitorexit,設定進入數為0為止。

如果synchronized加在普通方法上,那麼有效的範圍是多個執行緒執行同一個物件的方法。通過上面的解釋應該比較容易理解了,因為不同的物件獲取的是不同的monitor監視器,自然也就不存在佔用–等待的過程了。如果是載入static方法上那麼需要獲取的就是這個物件所在class的Class物件,所以此時不管是幾個物件,對應的都是同一個class物件,也就是說多個執行緒又存在對同一個monitor的佔用—等待的過程了。所以說載入static上是對於整個類檔案有效。

 

 

轉載自-- https://www.cnblogs.com/jurendage/p/8691975.html