Java多執行緒的悲觀鎖與樂觀鎖及各自適用場景

點點滴滴的記錄發表於2018-04-06

悲觀鎖

      悲觀鎖,就是不管是否發生多執行緒衝突,只要存在這種可能,就每次訪問都加鎖,加鎖就會導致鎖之間的爭奪,有爭奪就會有輸贏,輸者等待。

      syncrhoized是一種獨佔鎖,即:佔用該鎖的執行緒才可以執行,申請該鎖的執行緒就只能掛起等待,直到佔用鎖的執行緒釋放鎖才喚醒,拿到鎖並執行。由於在程式掛起和恢復執行過程中存在著很大的開銷,並且當一個執行緒正在等待鎖時,它不能做任何事。所以syncrhoized是一種悲觀鎖,凡是用syncrhoized加了鎖的多執行緒之間都會因鎖的爭奪結果導致掛起、喚醒等開銷。

 

樂觀鎖

      獲得鎖後一直持有鎖以防本執行緒再次申請該鎖造成無謂的解鎖再加鎖開銷,或者假設沒有衝突而去完成同步程式碼塊如果衝突再迴圈重試,或者採取申請鎖失敗後不立刻掛起而是稍微等待再次嘗試獲取 等待策略,以減少執行緒因為掛起、阻塞、喚醒(發生CPU的排程切換) 而造成的開銷。

      偏向鎖、輕量級鎖(CAS輪詢)、自旋鎖 就是基於上述思路的樂觀鎖

 

      在多執行緒的加鎖機制中,JVM會首先嚐試樂觀鎖,失敗後才呼叫悲觀鎖。


適用場景:

悲觀鎖:比較適合寫入操作比較頻繁的場景,如果出現大量的讀取操作,每次讀取的時候都會進行加鎖,這樣會增加大量的鎖的開銷,降低了系統的吞吐量。

樂觀鎖:比較適合讀取操作比較頻繁的場景,如果出現大量的寫入操作,資料發生衝突的可能性就會增大,為了保證資料的一致性,應用層需要不斷的重新獲取資料,這樣會增加大量的查詢操作,降低了系統的吞吐量。

總結:兩種所各有優缺點,讀取頻繁使用樂觀鎖,寫入頻繁使用悲觀鎖。


相關文章