如何保證集合是線程安全的?ConcurrentHashMap如何實現(xiàn)高效的線程安全?

問題:

  • 如何保證集合是線程安全的?
  • ConcurrentHashMap如何實現(xiàn)高效的線程安全?

知識點:

  1. 為什么需要ConcurrentHashMap?
    Hashtable比較低效,所有線程公用同一把鎖,效率低下。Collections工具類提供的Map方法,大同小異,源碼如下:
private static class SynchronizedMap<K, V> implements Map<K, V>, Serializable {
        private static final long serialVersionUID = 1978198479659022715L;
        private final Map<K, V> m;
        //劃重點了,利用this作為互斥的mutex
        final Object mutex;
        private transient Set<K> keySet;
        private transient Set<Entry<K, V>> entrySet;
        private transient Collection<V> values;

        SynchronizedMap(Map<K, V> var1) {
            this.m = (Map)Objects.requireNonNull(var1);
            this.mutex = this;
        }

        SynchronizedMap(Map<K, V> var1, Object var2) {
            this.m = var1;
            this.mutex = var2;
        }

        public int size() {
            Object var1 = this.mutex;
         synchronized(this.mutex) {
                return this.m.size();
            }
        }

        public boolean isEmpty() {
            Object var1 = this.mutex;
           //方法不再申明為synchronized方法,但是利用this作為互斥的mutex,大同小異 synchronized(this.mutex) {
                return this.m.isEmpty();
            }
        }

高并發(fā)時候,容易始HashMap死循環(huán)導(dǎo)致CPU占用100%??蓞⒖?a target="_blank" rel="nofollow">不正當(dāng)使用HashMap導(dǎo)致cpu 100%的問題追究,
HashMap 死循環(huán)的探究

  1. ConcurrentHashMap,篇幅太長,后續(xù)有專門文章分析。

回答問題

Java提供了不同層面的線程安全支持,在傳統(tǒng)的框架內(nèi)部,除了Hashtable等同步容器,還提供了所謂的同步包裝器,我們可以調(diào)用Collecions工具的同步方法,來獲取一個同步的包裝容器(如:Collections.synchronizedMap),但是他們都是利用非常粗粒度的處理方式,在高并發(fā)的時候,性能比較低下。

另外,更加普遍的選擇是利用并發(fā)包提供的線程安全容器類,它提供了:

具體保證線程安全的方式,包括從有簡單的synchronize方式,到基于更加精細化的,比如基于分離鎖實現(xiàn)的ConcurrentHashMap等并發(fā)實現(xiàn)等。具體選擇要看開發(fā)的場景需求。總得來說,并發(fā)包提供的容器通用場景,遠優(yōu)于早期的簡單的同步實現(xiàn)。
自己項目中使用代碼:

private Map<Promise, ReadableMap> mPictureTakenOptions = new ConcurrentHashMap<>();
  private Map<Promise, File> mPictureTakenDirectories = new ConcurrentHashMap<>();
  
public void takePicture(ReadableMap options, final Promise promise, File cacheDirectory) {
    mPictureTakenPromises.add(promise);
    mPictureTakenOptions.put(promise, options);
    mPictureTakenDirectories.put(promise, cacheDirectory);
    if (mPlaySoundOnCapture) {
      MediaActionSound sound = new MediaActionSound();
      sound.play(MediaActionSound.SHUTTER_CLICK);
    }
    try {
      super.takePicture();
    } catch (Exception e) {
      mPictureTakenPromises.remove(promise);
      mPictureTakenOptions.remove(promise);
      mPictureTakenDirectories.remove(promise);
      throw e;
    }
  }

參考:

聲明:此為原創(chuàng),轉(zhuǎn)載請聯(lián)系作者


作者:微信公眾號添加公眾號-遛狗的程序員 ,或者可以掃描以下二維碼關(guān)注相關(guān)技術(shù)文章。

qrcode_for_gh_1ba0785324d6_430.jpg

當(dāng)然喜愛技術(shù),樂于分享的你也可以可以添加作者微信號:

WXCD.jpeg
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在一個方法內(nèi)部定義的變量都存儲在棧中,當(dāng)這個函數(shù)運行結(jié)束后,其對應(yīng)的棧就會被回收,此時,在其方法體中定義的變量將不...
    Y了個J閱讀 4,575評論 1 14
  • Java8張圖 11、字符串不變性 12、equals()方法、hashCode()方法的區(qū)別 13、...
    Miley_MOJIE閱讀 3,899評論 0 11
  • mark一下在mac上安裝完成openfire后,打開網(wǎng)站出現(xiàn)java報錯??梢栽偃グ惭b一下jdk試試。 open...
    上玄月_lxl閱讀 229評論 0 1
  • 好孩子是培養(yǎng)出來的,這話不無道理。但我要說,好孩子是帶出來的,是良好的家庭氛圍中帶出來的。女兒的成長歷程,足以可以...
    瀟然雨嘉閱讀 366評論 1 1
  • 一直堅持每個周末都給孩子準(zhǔn)備“愛心早餐”,中間由于裝修房子,耽誤了幾個月。但這份“愛心”從來不會間斷,因為愛始...
    愛瑪?shù)奈⑿?/span>閱讀 617評論 0 0

友情鏈接更多精彩內(nèi)容