6、Synchronized與Lock原理
1)、Synchronized與Lock區別:
a)、synchronized是一個關鍵字,在程式碼執行時出現異常,JVM會自動釋放鎖,
Lock是一個介面,要保證鎖被釋放,就必須在finally中執行unLock();
b)、synchronized屬於隱式鎖,不能實現公平鎖;
Lock是顯式鎖,可實現公平鎖,可以對鎖進行控制,可以中斷
c)、synchronized作用在static方法上時候,為全域性鎖;作用在非static方法上時,為物件鎖
2)、Synchronized原理:
Synchronized作用於方法時:
JVM可以從方法常量池中的方法表結構(method_info Structure) 中的
ACC_SYNCHRONIZED訪問標誌區分一個方法是否同步方法。當方法呼叫時,
呼叫指令將會 檢查方法的ACC_SYNCHRONIZED訪問標誌是否被設定,
如果設定了,執行執行緒將先持有monitor,然後再執行方法,最後再方法完成
(無論是正常完成還是非正常完成)時釋放monitor。在方法執行期間,
執行執行緒持有了monitor,其他任何執行緒都無法再獲得同一個monitor。
如果一個同步方法執行期間拋 出了異常,並且在方法內部無法處理此異常,
那這個同步方法所持有的monitor將在異常拋到同步方法之外時自動釋放。
Synchronized作用於同步程式碼塊時:
通過一個monitor(監視器鎖)的物件來完成,使用monitorenter 和 monitorexit指令,
monitorenter指令指向同步程式碼塊的開始位置,monitorexit指令則指明同步程式碼塊的
結束位置,當執行monitorenter指令時當monitor被佔用時就會處於鎖定狀態,執行緒執行
monitorenter指令時嘗試獲取物件所對應的monitor所有權,倘若其他執行緒已經擁有
物件的 monitor所有權,那當前執行緒將被阻塞,直到正在執行執行緒執行完畢,
即monitorexit指令被執行。流程如下:
a)、如果monitor的進入數為0,則該執行緒進入monitor,然後將進入數設定為1,
該執行緒即為monitor的所有者。
b)、如果執行緒已經佔有該monitor,只是重新進入,則進入monitor的進入數加1.
c)、如果其他執行緒已經佔用了monitor,則該執行緒進入阻塞狀態,直到monitor的
進入數為0,再重新嘗試獲取monitor的所有權。
3)、Lock原理:
Lock實現類是ReetrantLock。ReetrantLock是基於AQS(AbstractQueuedSynchronizer又
稱為佇列同步器)併發框架實現的。
AQS原理:
內部通過一個int型別的成員變數state來控制同步狀態,當state=0時,則說明沒有
任何執行緒佔有共享資源的鎖,當state=1時,則說明有執行緒目前正在使用共享變數,
其他執行緒必須加入同步佇列(FIFO的雙向連結串列佇列)進行等待,AQS內部通過
內部類Node構成FIFO的同步佇列來完成執行緒獲取鎖的排隊工作,同時利用內部類
ConditionObject構建等待佇列,當Condition呼叫wait()方法後,執行緒將會加入
等待佇列中,而當Condition呼叫signal()方法後,執行緒將從等待佇列轉移動
同步佇列中進行鎖競爭。注意這裡涉及到兩種佇列,一種的同步佇列,當執行緒請求鎖
而等待的後將加入同步佇列等待,而另一種則是等待佇列(可有多個),通過Condition
呼叫await()方法釋放鎖後,將加入等待佇列。
ReetrantLock原理:
重入鎖ReentrantLock,是一個基於AQS併發框架的併發控制類,其內部實現了3個類,
分別是Sync、NoFairSync、FairSync類,其中Sync繼承自AQS,實現了釋放鎖的
模板方法tryRelease(int),而NoFairSync和FairSync都繼承自Sync,實現各種
獲取鎖的方法tryAcquire(int)。ReentrantLock的所有方法實現幾乎都間接呼叫了
這3個類
複製程式碼
附上一個ReentrantLock(原始碼解析流程)流程圖(網上找的):