眾所周知synchronized
關鍵字是解決併發問題常用解決方案,有以下三種使用方式:
實現原理:jvm
是通過進入、退出物件監視器(monitor
)來實現對方法、同步塊的同步的。
具體實現是在編譯之後在同步方法呼叫前加入乙個monitor.enter
指令,在退出方法和異常處插入monitor.exit
的指令。
其本質就是對乙個物件監視器(monitor
)進行獲取,而這個獲取過程具有排他性從而達到了同一時刻只能乙個執行緒訪問的目的。
而對於沒有獲取到鎖的執行緒將會阻塞到方法入口處,直到獲取鎖的執行緒monitor.exit
之後才能嘗試繼續獲取鎖。
2.鎖優化
synchronized
很多都稱之為重量鎖,jdk1.6
中對synchronized
進行了各種優化,為了能減少獲取和釋放鎖帶來的消耗引入了偏向鎖
和輕量鎖
。
當**進入同步塊時,如果同步物件為無鎖狀態時,當前執行緒會在棧幀中建立乙個鎖記錄(lock record
)區域,同時將鎖物件的物件頭中mark word
拷貝到鎖記錄中,再嘗試使用cas
將mark word
更新為指向鎖記錄的指標。
如果更新成功,當前執行緒就獲得了鎖。
如果更新失敗jvm
會先檢查鎖物件的mark word
是否指向當前執行緒的鎖記錄。
如果是則說明當前執行緒擁有鎖物件的鎖,可以直接進入同步塊。
不是則說明有其他執行緒搶占了鎖,如果存在多個執行緒同時競爭一把鎖,輕量鎖就會膨脹為重量鎖。
解鎖輕量鎖的解鎖過程也是利用cas
來實現的,會嘗試鎖記錄替換回鎖物件的mark word
。如果替換成功則說明整個同步操作完成,失敗則說明有其他執行緒嘗試獲取鎖,這時就會喚醒被掛起的執行緒(此時已經膨脹為重量鎖
)
輕量鎖能提公升效能的原因是:
認為大多數鎖在整個同步週期都不存在競爭,所以使用cas
比使用互斥開銷更少。但如果鎖競爭激烈,輕量鎖就不但有互斥的開銷,還有cas
的開銷,甚至比重量鎖更慢。
為了進一步的降低獲取鎖的代價,jdk1.6
之後還引入了偏向鎖。
偏向鎖的特徵是:鎖不存在多執行緒競爭,並且應由乙個執行緒多次獲得鎖。
當執行緒訪問同步塊時,會使用cas
將執行緒 id 更新到鎖物件的mark word
中,如果更新成功則獲得偏向鎖,並且之後每次進入這個物件鎖相關的同步塊時都不需要再次獲取鎖了。
釋放鎖當有另外乙個執行緒獲取這個鎖時,持有偏向鎖的執行緒就會釋放鎖,釋放時會等待全域性安全點(這一時刻沒有位元組碼執行),接著會暫停擁有偏向鎖的執行緒,根據鎖物件目前是否被鎖來判定將物件頭中的mark word
設定為無鎖或者是輕量鎖狀態。
偏向鎖可以提高帶有同步卻沒有競爭的程式效能,但如果程式中大多數鎖都存在競爭時,那偏向鎖就起不到太大作用。可以使用-xx:-usebiasedlocking
來關閉偏向鎖,並預設進入輕量鎖。
synchronized關鍵字解析
一 修飾方法 1.修飾普通方法 對呼叫此方法的物件加鎖 2.修飾static方法 對呼叫此方法的類的所有物件加鎖 3.不能修飾構造方法,但是可以在構造方法內部修飾 塊 二 修飾 塊 1.synchronized this 相當於修飾普通方法 2.synchronized a.class 相當於修飾s...
解讀synchronized關鍵字
size large 最近在寫多執行緒程式,網上收集總結了synchronized的用法,結果如下 size 1 synchronized關鍵字的作用域有二種 1 是某個物件例項內,synchronized amethod 可以防止多個執行緒同時訪問這個物件的synchronized方法 如果乙個物...
synchronized 關鍵字分析
synchronized是典型的可衝入鎖,jdk1.5之後做了較大的優化 如圖,synchronized可以用在方法上也可以使用在 塊中,其中方法是例項方法和靜態方法分別鎖的是該類的例項物件和該類的物件。而使用在 塊中也可以分為三種,具體的可以看上面的 這裡的需要注意的是 如果鎖的是類物件的話,儘管...