欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時(shí)間:2017年08月21日 15:13:40   作者:正在長(zhǎng)大的毛毛蟲(chóng)  
本篇文章主要介紹了java高并發(fā)鎖的3種實(shí)現(xiàn)示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

初級(jí)技巧 - 樂(lè)觀鎖

樂(lè)觀鎖適合這樣的場(chǎng)景:讀不會(huì)沖突,寫(xiě)會(huì)沖突。同時(shí)讀的頻率遠(yuǎn)大于寫(xiě)。

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

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

樂(lè)觀鎖的實(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); 
} 

中級(jí)技巧 - String.intern()

樂(lè)觀鎖不能很好解決大量寫(xiě)沖突問(wèn)題,但是如果很多場(chǎng)景下,鎖實(shí)際上只是針對(duì)某個(gè)用戶或者某個(gè)訂單。比如一個(gè)用戶必須先創(chuàng)建session,才能進(jìn)行后面的操作。但是由于網(wǎng)絡(luò)原因,創(chuàng)建用戶session的請(qǐng)求和后續(xù)請(qǐng)求幾乎同時(shí)達(dá)到,而并行線程可能會(huì)先處理后續(xù)請(qǐng)求。一般情況,需要對(duì)用戶sessionMap加鎖,比如上面的樂(lè)觀鎖。在這種場(chǎng)景下,可以講鎖限定到用戶本身上,即從原來(lái)的

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è)比較類(lèi)似于數(shù)據(jù)庫(kù)表鎖和行鎖的概念,顯然行鎖的并發(fā)能力比表鎖高很多。

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

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

CopyOnWriteMap?

既然說(shuō)到了“類(lèi)似于數(shù)據(jù)庫(kù)中的行鎖的概念”,就不得不提一下MVCC,Java中CopyOnWrite類(lèi)實(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)行修改,完成之后,再用修改后的副本,替換掉原來(lái)的數(shù)據(jù)。這種方法就叫做Copy On Write。

但是,,,JDK并沒(méi)有提供CopyOnWriteMap,為什么?下面有個(gè)很好的回答,那就是已經(jīng)有了ConcurrentHashMap,為什么還需要CopyOnWriteMap?

Fredrik Bromee 寫(xiě)道

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.

高級(jí)技巧 - 類(lèi)ConcurrentHashMap

String.inter()的缺陷是類(lèi) String 維護(hù)一個(gè)字符串池是放在JVM perm區(qū)的,如果用戶數(shù)特別多,導(dǎo)致放入字符串池的String不可控,有可能導(dǎo)致OOM錯(cuò)誤或者過(guò)多的Full GC。怎么樣能控制鎖的個(gè)數(shù),同時(shí)減小粒度鎖呢?直接使用Java ConcurrentHashMap?或者你想加入自己更精細(xì)的控制?那么可以借鑒ConcurrentHashMap的方式,將需要加鎖的對(duì)象分為多個(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 
  } 
} 

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java實(shí)現(xiàn)基礎(chǔ)銀行ATM系統(tǒng)

    Java實(shí)現(xiàn)基礎(chǔ)銀行ATM系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)基礎(chǔ)銀行ATM系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Spring Boot部署到Tomcat過(guò)程中遇到的問(wèn)題匯總

    Spring Boot部署到Tomcat過(guò)程中遇到的問(wèn)題匯總

    這篇文章主要給大家分享了關(guān)于Spring Boot部署到Tomcat過(guò)程中遇到的一些問(wèn)題,文中將解決的方法介紹非常詳細(xì),對(duì)同樣遇到這個(gè)問(wèn)題的朋友具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-03-03
  • Java集合中的LinkedHashMap使用解析

    Java集合中的LinkedHashMap使用解析

    這篇文章主要介紹了Java集合中的LinkedHashMap使用解析,LinkedHashMap是繼承于HashMap的,所以它的很多屬性和方法都是HashMap中的,那么它是怎么實(shí)現(xiàn)有序存儲(chǔ)的呢,需要的朋友可以參考下
    2023-12-12
  • java實(shí)現(xiàn)字符串匹配求兩個(gè)字符串的最大公共子串

    java實(shí)現(xiàn)字符串匹配求兩個(gè)字符串的最大公共子串

    這篇文章主要介紹了java實(shí)現(xiàn)求兩個(gè)字符串最大公共子串的方法,詳細(xì)的描述了兩個(gè)字符串的最大公共子串算法的實(shí)現(xiàn),需要的朋友可以參考下
    2016-10-10
  • 新手必備的IDEA常用設(shè)置總結(jié)

    新手必備的IDEA常用設(shè)置總結(jié)

    今天給大家總結(jié)了一些IDEA的常用設(shè)置,文中有非常詳細(xì)的圖文介紹,對(duì)正在學(xué)習(xí)使用IDEA的小伙伴們很有幫助,需要的朋友可以參考下
    2021-05-05
  • java各種類(lèi)型對(duì)象占用內(nèi)存情況分析

    java各種類(lèi)型對(duì)象占用內(nèi)存情況分析

    這篇文章主要介紹了java各種類(lèi)型對(duì)象占用內(nèi)存情況分析,對(duì)內(nèi)存或者性能優(yōu)化感興趣的同學(xué),一定要看一下
    2021-04-04
  • Java實(shí)體類(lèi)中Set按照對(duì)象的某個(gè)字段對(duì)set排序

    Java實(shí)體類(lèi)中Set按照對(duì)象的某個(gè)字段對(duì)set排序

    這篇文章主要介紹了Java實(shí)體類(lèi)中Set按照對(duì)象的某個(gè)字段對(duì)set排序,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-06-06
  • 一文詳解Java中枚舉類(lèi)的使用

    一文詳解Java中枚舉類(lèi)的使用

    這篇文章主要介紹了深入淺出講解Java中的枚舉類(lèi),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,感興趣的朋友可以了解下
    2022-11-11
  • 詳解Java中的checked異常和unchecked異常區(qū)別

    詳解Java中的checked異常和unchecked異常區(qū)別

    這篇文章主要介紹了詳解Java中的checked異常和unchecked異常區(qū)別,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-02-02
  • 你知道Spring中為何不建議使用字段注入嗎

    你知道Spring中為何不建議使用字段注入嗎

    這篇文章主要給大家介紹了關(guān)于Spring中為何不建議使用字段注入的相關(guān)資料,通過(guò)本文你將對(duì)Spring的引入方式有更一步的了解,需要的朋友可以參考下
    2021-08-08

最新評(píng)論