synchronized 與 lock


synchronized 與 lock


(1)代碼層

Lock是基於在語言層面實現的鎖,Lock鎖可以被中斷,支持定時鎖。在安全的前提下,可以很隨意的釋放鎖,如果安全的話。


Synchronized是基於JVM實現的,稱之爲對象的內置鎖,Java中的每一個對象都可以作爲鎖。

1)對於同步方法,鎖是當前實例對象。

2)對於靜態同步方法,鎖是當前對象的Class對象。

3)對於同步方法塊,鎖是Synchonized括號裏配置的對象。當一個線程訪問同步代碼塊時,它首先必須得到鎖,退出或拋出異常時必須釋放鎖。


JVM基於進入和退出Monitor對象來實現方法同步和代碼塊同步,但兩者的實現細節不一樣。


代碼塊同步是使用monitorenter和monitorexit指令實現,而方法同步是使用另外一種方式實現的,細節在JVM規範裏並沒有詳細說明,但是方法的同步同樣可以使用這兩個指令來實現。

monitorenter指令是在編譯後插入到同步代碼塊的開始位置,而monitorexit是插入到方法結束處和異常處,每個monitorenter必須有一個monitorexit對應。任何對象都有一個 monitor 與之關聯,當且一個monitor 被持有後,它將處於鎖定狀態。

線程執行到 monitorenter 指令時,將會嘗試獲取對象所對應的 monitor 的所有權,即嘗試獲得對象的鎖。

其實無論是Lock還是Synchronized,他們加鎖的機制,使用的機器指令,系統調用都基本一致。

 

(2)效率上的區別

當競爭不是很激烈的時候Synchronized使用的是輕量級鎖或者偏向鎖,這兩種鎖都能有效減少輪詢或者阻塞的發生,相比與Lock仍舊要將未獲得鎖的線程放入等待隊列阻塞帶來的上下文切換的開銷,此時Synchronized效率會高些,當競爭激烈的時候Synchronized會升級爲重量級鎖,由於Synchronized的出對速度相比Lock要慢,所以Lock的效率會更高些。一般對於數據結構設計或者框架的設計都傾向於使用Lock而非Synchronized。


(3)其他

1)注意鎖的粒度性


2) synchronized  鎖只鎖括號裏面的代碼內容,一個方法或者一個類等等。如果被鎖的代碼拋出異常會自動釋                 放鎖資源。


3)鎖鎖定 lock 和 unlock 之間的代碼,被鎖的代碼拋出異常不會自動釋放鎖資源,需要 try catch  後在 finally 裏

     面手動 unlock 釋放鎖資源


另外補充:

java之yield(),sleep(),wait()區別詳解


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