Java鎖的最佳化

541732025發表於2014-03-30

在java中,執行緒安全是透過鎖來實現的,但是如果你對鎖的工作機制有所瞭解,就會發現這個東西很耗效能。為了最佳化鎖機制,從java6開始,引入了偏向鎖、輕量級鎖,目的是為了減少多執行緒進入互斥的機率,甚至消除同步原語,以提高效能。
它是怎樣實現的呢?它並不是要消除互斥,而只是儘量在進入互斥前,利用CPU原語Compare-And-Swap(CAS,彙編指令CMPXCHG),進行效能的補救。
在講各偏向鎖、輕量級鎖之前,需要先講講Object Header(物件頭),Object Header是一個2字(1 word = 4byte)長度的儲存區域。
第一個字的用來標記同步、GC、以及hash code等,官方稱之為
mark word第二個字儲存指向到物件的class,mark word是實現輕量級鎖的關鍵,在執行期間,mark word儲存的資料會隨著鎖標誌位的變化而變化,



一,偏向鎖
偏向鎖,顧名思義,就是偏向第一個訪問鎖的執行緒,如果在接下來的執行過程中,該鎖沒有其它執行緒訪問,則持有偏向鎖的執行緒永遠不需要觸發同步。
1,當第一個執行緒進入同步塊時,如果偏向鎖的標誌為1(說明還處於偏向鎖的層次),而且記錄執行緒ID的位置為空(說明沒有其他執行緒來競爭),則在mark word裡記錄當前執行緒的ID,當前執行緒成功獲取了偏向鎖,以後再進入、退出同步塊時,都不需要CAS、加鎖解鎖操作,只需比較一下mark word裡儲存的是否是本執行緒的ID。
2,如果偏向鎖標誌為1,但是記錄執行緒ID的位置不是本執行緒的ID,則表明其他執行緒獲取了偏向鎖,這時候會將持有偏向鎖的執行緒掛起,然後將鎖膨脹至輕量級鎖。
3,如果偏向鎖標誌不是1,則說明鎖的層級早已經膨脹為輕量級鎖,甚至重量級鎖了。
以上說明,偏向鎖只能在單執行緒環境下起作用。在java6下,偏向鎖預設是開啟的,如果同步程式碼一直都是多執行緒訪問的,那麼消除偏向鎖這一步驟就是多餘的,那麼你可以禁用偏向鎖-XX:UseBiasedLocking,畢竟消除偏向鎖的開銷還是蠻大的。

二,輕量級鎖
輕量級鎖實現的關鍵為CAS,透過底層CPU原語來做到避免同步的開銷
1,當執行緒進入同步塊時,為執行緒分配lock record,將mark word複製至lock record,然後嘗試將mark word指標指向當前執行緒lock record(標誌鎖已經被佔用了),lock record owner指標指向mark word(讓執行緒知道鎖的是哪個物件),如果都成功,則該執行緒成功獲取輕量級鎖。
2,如果發現mark word指標已經指向了其它執行緒,說明其他執行緒已經獲取了輕量級鎖,這時候,該執行緒就會修改mark word中的重量級指標,並且自己採用自旋的方式等待鎖。
3,當獲取輕量級鎖的執行緒釋放鎖時,會拿lock record中事先複製的mark word與object head中的mark word比較,如果一樣,則說明沒有其他執行緒競爭,順利釋放鎖,如果不同,則說明存在其他執行緒競爭,鎖就會膨脹為重量級鎖。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28912557/viewspace-1132799/,如需轉載,請註明出處,否則將追究法律責任。

相關文章