java高並發鎖的3種實現


提到鎖,大家可能都會想到synchronized關鍵字,使用它的確可以解決一切並發問題,但是對於系統吞吐要求更高的,在這里提供了幾個小技巧,幫助大家減小鎖粒度,提高系統並發能力。

初級技巧 - 樂觀鎖

樂觀鎖適合這樣的場景:讀不會沖突,寫會沖突。同時讀的頻率遠大於寫。

以下面的代碼為例,悲觀鎖的實現:

 

 樂觀鎖的實現:

 

 

中級技巧 - String.intern()

樂觀鎖不能很好解決大量寫沖突問題,但是如果很多場景下,鎖實際上只是針對某個用戶或者某個訂單。比如一個用戶必須先創建session,才能進行后面的操作。但是由於網絡原因,創建用戶session的請求和后續請求幾乎同時達到,而並行線程可能會先處理后續請求。一般情況,需要對用戶sessionMap加鎖,比如上面的樂觀鎖。在這種場景下,可以講鎖限定到用戶本身上,即從原來的

lock.lock();

    int num=storage.get(key);

    storage.set(key,num+1);

lock.unlock();

更改為:

lock.lock(key);

    int num=storage.get(key);

    storage.set(key,num+1);

lock.unlock(key);

這個比較類似於數據庫表鎖和行鎖的概念,顯然行鎖的並發能力比表鎖高很多。

使用String.inter()是這種思路的一種具體實現。類 String 維護一個字符串池。 當調用 intern 方法時,如果池已經包含一個等於此 String 對象的字符串(該對象由 equals(Object) 方法確定),則返回池中的字符串。可見,當String相同時,String.intern()總是返回同一個對象,因此就實現了對同一用戶加鎖。由於鎖的粒度局限於具體用戶,使系統獲得了最大程度的並發。

 

 

CopyOnWriteMap?

既然說到了“類似於數據庫中的行鎖的概念”,就不得不提一下MVCC,Java中CopyOnWrite類實現了MVCC。Copy On Write是這樣一種機制。當我們讀取共享數據的時候,直接讀取,不需要同步。當我們修改數據的時候,我們就把當前數據Copy一份副本,然后在這個副本 上進行修改,完成之后,再用修改后的副本,替換掉原來的數據。這種方法就叫做Copy On Write。

但是,,,JDK並沒有提供CopyOnWriteMap,為什么?下面有個很好的回答,那就是已經有了ConcurrentHashMap,為什么還需要CopyOnWriteMap?

 

 

高級技巧 - 類ConcurrentHashMap

String.inter()的缺陷是類 String 維護一個字符串池是放在JVM perm區的,如果用戶數特別多,導致放入字符串池的String不可控,有可能導致OOM錯誤或者過多的Full GC。怎么樣能控制鎖的個數,同時減小粒度鎖呢?直接使用Java ConcurrentHashMap?或者你想加入自己更精細的控制?那么可以借鑒ConcurrentHashMap的方式,將需要加鎖的對象分為多個bucket,每個bucket加一個鎖,偽代碼如下:

 

 來源:https://blog.csdn.net/qq_38972548/article/details/81162913

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM