中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何在java項目中實現一個高并發鎖

發布時間:2020-12-02 16:42:34 來源:億速云 閱讀:177 作者:Leah 欄目:編程語言

如何在java項目中實現一個高并發鎖?相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

樂觀鎖

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

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

public Object get(Object key) { 
  synchronized(map) { 
   if(map.get(key) == null) { 
     // set some values 
   } 
    return map.get(key); 
  } 
} 

樂觀鎖的實現:

public Object get(Object key) { 
  Object val = null; 
  if((val = map.get(key) == null) { 
    // 當map取值為null時再加鎖判斷 
    synchronized(map) { 
      if(val = map.get(key) == null) { 
        // set some value to map... 
      } 
    } 
  } 
  return map.get(key); 
} 

中級技巧 - 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()總是返回同一個對象,因此就實現了對同一用戶加鎖。由于鎖的粒度局限于具體用戶,使系統獲得了最大程度的并發。

public void doSomeThing(String uid) { 
  synchronized(uid.intern()) { 
    // ... 
  } 
}

CopyOnWriteMap?

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

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

Fredrik Bromee 寫道

I guess this depends on your use case, but why would you need a CopyOnWriteMap when you already have a ConcurrentHashMap?

For a plain lookup table with many readers and only one or few updates it is a good fit.

Compared to a copy on write collection:

Read concurrency:

Equal to a copy on write collection. Several readers can retrieve elements from the map concurrently in a lock-free fashion.

Write concurrency:

Better concurrency than the copy on write collections that basically serialize updates (one update at a time). Using a concurrent hash map you have a good chance of doing several updates concurrently. If your hash keys are evenly distributed.

If you do want to have the effect of a copy on write map, you can always initialize a ConcurrentHashMap with a concurrency level of 1.

高級技巧 - 類ConcurrentHashMap

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

Map locks = new Map(); 
List lockKeys = new List(); 
for(int number : 1 - 10000) { 
  Object lockKey = new Object(); 
  lockKeys.add(lockKey); 
  locks.put(lockKey, new Object()); 
}  
public void doSomeThing(String uid) { 
  Object lockKey = lockKeys.get(uid.hash() % lockKeys.size()); 
  Object lock = locks.get(lockKey); 
  synchronized(lock) { 
   // do something 
  } 
} 

看完上述內容,你們掌握如何在java項目中實現一個高并發鎖的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

洛隆县| 西华县| 招远市| 家居| 民勤县| 普定县| 明光市| 南平市| 中西区| 安徽省| 伊吾县| 集安市| 陆良县| 巍山| 许昌县| 三穗县| 东乡县| 博白县| 汉阴县| 玉门市| 探索| 隆尧县| 宁波市| 霸州市| 泰来县| 通化市| 哈尔滨市| 永德县| 涞源县| 西乌| 丹凤县| 凤凰县| 三门县| 旺苍县| 长泰县| 岳西县| 荥阳市| 长寿区| 万宁市| 乌兰县| 上虞市|