java高并發(fā)鎖的3種實(shí)現(xiàn)

提到鎖畔乙,大家可能都會想到synchronized關(guān)鍵字君仆,使用它的確可以解決一切并發(fā)問題,但是對于系統(tǒng)吞吐要求更高的牲距,在這里提供了幾個(gè)小技巧返咱,幫助大家減小鎖粒度,提高系統(tǒng)并發(fā)能力牍鞠。

初級技巧 - 樂觀鎖
樂觀鎖適合這樣的場景:讀不會沖突咖摹,寫會沖突。同時(shí)讀的頻率遠(yuǎn)大于寫难述。

以下面的代碼為例萤晴,悲觀鎖的實(shí)現(xiàn):

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

樂觀鎖的實(shí)現(xiàn):

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

中級技巧 - String.intern()
樂觀鎖不能很好解決大量寫沖突問題,但是如果很多場景下胁后,鎖實(shí)際上只是針對某個(gè)用戶或者某個(gè)訂單店读。比如一個(gè)用戶必須先創(chuàng)建session,才能進(jìn)行后面的操作攀芯。但是由于網(wǎng)絡(luò)原因屯断,創(chuàng)建用戶session的請求和后續(xù)請求幾乎同時(shí)達(dá)到,而并行線程可能會先處理后續(xù)請求。一般情況殖演,需要對用戶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);

這個(gè)比較類似于數(shù)據(jù)庫表鎖和行鎖的概念,顯然行鎖的并發(fā)能力比表鎖高很多朋鞍。

使用String.inter()是這種思路的一種具體實(shí)現(xiàn)已添。類 String 維護(hù)一個(gè)字符串池。 當(dāng)調(diào)用 intern 方法時(shí)滥酥,如果池已經(jīng)包含一個(gè)等于此 String 對象的字符串(該對象由 equals(Object) 方法確定)更舞,則返回池中的字符串】参牵可見缆蝉,當(dāng)String相同時(shí),String.intern()總是返回同一個(gè)對象瘦真,因此就實(shí)現(xiàn)了對同一用戶加鎖刊头。由于鎖的粒度局限于具體用戶,使系統(tǒng)獲得了最大程度的并發(fā)诸尽。

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

CopyOnWriteMap原杂?
既然說到了“類似于數(shù)據(jù)庫中的行鎖的概念”,就不得不提一下MVCC您机,Java中CopyOnWrite類實(shí)現(xiàn)了MVCC穿肄。Copy On Write是這樣一種機(jī)制。當(dāng)我們讀取共享數(shù)據(jù)的時(shí)候际看,直接讀取咸产,不需要同步。當(dāng)我們修改數(shù)據(jù)的時(shí)候仲闽,我們就把當(dāng)前數(shù)據(jù)Copy一份副本脑溢,然后在這個(gè)副本 上進(jìn)行修改,完成之后赖欣,再用修改后的副本屑彻,替換掉原來的數(shù)據(jù)。這種方法就叫做Copy On Write畏鼓。
但是酱酬,壶谒,云矫,JDK并沒有提供CopyOnWriteMap,為什么汗菜?下面有個(gè)很好的回答让禀,那就是已經(jīng)有了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 維護(hù)一個(gè)字符串池是放在JVM perm區(qū)的巡揍,如果用戶數(shù)特別多痛阻,導(dǎo)致放入字符串池的String不可控,有可能導(dǎo)致OOM錯(cuò)誤或者過多的Full GC腮敌。怎么樣能控制鎖的個(gè)數(shù)阱当,同時(shí)減小粒度鎖呢?直接使用Java ConcurrentHashMap糜工?或者你想加入自己更精細(xì)的控制弊添?那么可以借鑒ConcurrentHashMap的方式,將需要加鎖的對象分為多個(gè)bucket捌木,每個(gè)bucket加一個(gè)鎖油坝,偽代碼如下:

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  
   }  
}  
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市刨裆,隨后出現(xiàn)的幾起案子澈圈,更是在濱河造成了極大的恐慌,老刑警劉巖帆啃,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瞬女,死亡現(xiàn)場離奇詭異,居然都是意外死亡努潘,警方通過查閱死者的電腦和手機(jī)拆魏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來慈俯,“玉大人渤刃,你說我怎么就攤上這事√欤” “怎么了卖子?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長刑峡。 經(jīng)常有香客問我洋闽,道長,這世上最難降的妖魔是什么突梦? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任诫舅,我火速辦了婚禮,結(jié)果婚禮上宫患,老公的妹妹穿的比我還像新娘刊懈。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布虚汛。 她就那樣靜靜地躺著匾浪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪卷哩。 梳的紋絲不亂的頭發(fā)上蛋辈,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天,我揣著相機(jī)與錄音将谊,去河邊找鬼冷溶。 笑死,一個(gè)胖子當(dāng)著我的面吹牛尊浓,可吹牛的內(nèi)容都是我干的挂洛。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼眠砾,長吁一口氣:“原來是場噩夢啊……” “哼虏劲!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起褒颈,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤柒巫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后谷丸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體堡掏,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年刨疼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了泉唁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,566評論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡揩慕,死狀恐怖亭畜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情迎卤,我是刑警寧澤拴鸵,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站蜗搔,受9級特大地震影響劲藐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜樟凄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一聘芜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缝龄,春花似錦汰现、人聲如沸挂谍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至百新,卻和暖如春企软,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背饭望。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工仗哨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人铅辞。 一個(gè)月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓厌漂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親斟珊。 傳聞我的和親對象是個(gè)殘疾皇子苇倡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 【轉(zhuǎn)】java高并發(fā)鎖的3種實(shí)現(xiàn) 標(biāo)簽:JAVA發(fā)布于 2017-06-01 09:59:50 初級技巧 - 樂觀...
    shine9609閱讀 720評論 0 2
  • 個(gè)人筆記,方便自己查閱使用 Contents Java LangAssignment, ReferenceData...
    freenik閱讀 1,370評論 0 6
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理囤踩,服務(wù)發(fā)現(xiàn)旨椒,斷路器,智...
    卡卡羅2017閱讀 134,626評論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法堵漱,類相關(guān)的語法综慎,內(nèi)部類的語法,繼承相關(guān)的語法勤庐,異常的語法示惊,線程的語...
    子非魚_t_閱讀 31,596評論 18 399
  • 五六章從船長這里學(xué)習(xí)到了“變現(xiàn)”、“轉(zhuǎn)化率”兩部分愉镰。 變現(xiàn)這部分從變現(xiàn)的理解米罚、變現(xiàn)的時(shí)間、變現(xiàn)的產(chǎn)品誤區(qū)丈探、三種主流...
    喵星人cici閱讀 272評論 0 0