国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

記一個 ConcurrentHashMap 使用不當導致的并發事故

開發
對于這類涉及并發操作的重構,建議梳理清晰的數據流向并結合源碼工作流程加以推斷分析,最終明確問題風險點直接進行邏輯修復并及時提測。

我們都知道ConcurrentHashMap可以保證鍵值對并發插入安全,因為其key值唯一性的原因,所以hutool對其進行了進一步的封裝實現了一個ConcurrentHashSet,代碼如下,即判斷put后是否返回null,若是null則說明是第一次插入,反之就是存在重復元素,返回已存在的元素值。從而保證并發插入元素線程安全且唯一。

//hutool的ConcurrentHashSet通過判斷返回null得知之前是否插入過重復元素
@Override
 public boolean add(E e) {
  return map.put(e, PRESENT) == null;
 }

但是如果對于這些映射容器的鍵使用不當就可能導致唯一鍵值對多次插入的情況,所以本文將基于筆者前段時間遇到的經典的例子為切入點,深入剖析該問題的原因和解決思路。

一、詳解ConcurrentHashMap并發重復插入問題

1. 需求說明

我們現在有這樣一個需求,大體是通過數據庫獲取要處理的任務并按照如下步驟執行:

  • 從數據庫讀取未完成(status為0)的任務,將其采用并發容器(ConcurrentHashSet)存放,key為這個任務對象
  • 工作線程處理,并在內存中將其設置為1
  • 定時任務線程從容器中讀取這些任務并移除
  • 將已完成任務狀態寫回庫中

2. 落地代碼

對應任務表的實體類封裝如下,我們的加載到ConcurrentHashSet會被多個線程并發的調度處理,處理過程中會并發更新狀態。

@Data
publicclass Task {
    
    privateint id;

    /**
     * 任務名稱
     */
    private String taskName;

    /**
     * 0.未開始
     * 1.進行中
     * 2.已完成
     */
    privateint status;


}

對應的實現代碼如下,可以看到從數據庫讀取未開始的任務,線程1將其更新為處理完成后更新為處理中,線程2處理完成后更新為已完成:

public static void main(String[] args) throws InterruptedException {
        ConcurrentHashSet<Task> set = new ConcurrentHashSet<>();
        CountDownLatch countDownLatch = new CountDownLatch(2);

        //假設從數據庫讀取一個task
        Task task = new Task();
        task.setId(1);
        task.setTaskName("任務1");
        task.setStatus(0);
        set.add(task);


        //模擬多線程并發更新

        //線程1更新為處理中
        new Thread(() -> {
            log.info("線程1處理中....");
            task.setStatus(1);
            set.add(task);

            countDownLatch.countDown();
        }, "t1").start();

        //線程2更新為已完成
        new Thread(() -> {
            log.info("線程2處理中....");
            task.setStatus(2);
            set.add(task);

            countDownLatch.countDown();
        }, "t2").start();


        countDownLatch.await();

        log.info("set size:{}", set.size());
    }

輸出結果如下,可以看到明明同一個對象,結果插入了3次:

00:44:32.637 [main] INFO com.sharkChili.webTemplate.Main - set size:3

調試查看set內部,3個元素都指向我們的唯一的任務-1。

3. 事故原因

我們都知道JDK8版本無論是HashMap還是ConcurrentHashMap底層采用數組+鏈表/紅黑樹,元素進行插入前都需要進行hash運算定位數組索引,然后使用equal和hashCode比較的過程元素是否存在。 很明顯,我們上文并發操作元素時修改了status字典,導致每次得出的hashCode結果值改變了,進而導致同一個元素因為不同的hashCode插入到不同的位置,出現去重失敗:

對應筆者也給出ConcurrentHashMap的put方法底層實現:

final V putVal(K key, V value, boolean onlyIfAbsent) {
        if (key == null || value == null) thrownew NullPointerException();
        //計算key的hash值,因為我們動態修改了status導致hash值不同
        int hash = spread(key.hashCode());
        int binCount = 0;
        for (Node<K,V>[] tab = table;;) {
            Node<K,V> f; int n, i, fh;
            if (tab == null || (n = tab.length) == 0)
                tab = initTable();
            //因為hash值不同每次定位到的i位置不同,最終存到不同的位置
            elseif ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
                if (casTabAt(tab, i, null,
                             new Node<K,V>(hash, key, value, null)))
                    break;                   // no lock when adding to empty bin
            }
  }
  .....
}

4. 解決方案

很明顯出現這個問題的原因就是因為并發操作修改的status影響了hashcode計算結果,進而導致并發操作變得無效,因為id是全局唯一的,所以直接重寫hashCode和equals方法,讓Task對象的計算和比對都通過id進行:

@Data
publicclass Task {

//......略

   @Override
    public boolean equals(Object o) {
        if (this == o) returntrue;
        if (o == null || getClass() != o.getClass()) returnfalse;
        Task task = (Task) o;
        return id == task.id;
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}

二、小結

總的來說,對于這類涉及并發操作的重構,建議梳理清晰的數據流向并結合源碼工作流程加以推斷分析,最終明確問題風險點直接進行邏輯修復并及時提測。

責任編輯:趙寧寧 來源: 寫代碼的SharkChili
相關推薦

2025-07-28 06:38:07

2021-09-11 19:00:54

Intro元素MemoryCache

2024-09-05 08:07:55

2022-10-25 18:00:00

Redis事務生產事故

2019-10-10 15:40:17

redisbug數據庫

2024-06-28 10:01:04

2022-06-21 11:24:05

多線程運維

2021-06-10 06:59:34

Redis應用API

2024-02-04 08:26:38

線程池參數內存

2020-10-22 07:09:19

TCP網絡協議

2021-05-20 10:02:50

系統Redis技巧

2009-12-17 14:53:52

VS2008程序

2021-08-26 14:26:25

Java代碼集合

2010-01-06 10:56:47

華為交換機使用

2020-11-16 12:35:25

線程池Java代碼

2021-07-11 09:34:45

ArrayListLinkedList

2011-08-18 13:49:32

筆記本技巧

2024-11-20 18:16:39

MyBatis批量操作數據庫

2022-04-08 08:48:16

線上事故日志訂閱者

2024-08-20 21:27:04

docker部署容器
點贊
收藏

51CTO技術棧公眾號

久久久久黄久久免费漫画| www.亚洲高清| 国产一区二区三区亚洲综合| 国产一区二区不卡在线 | 日韩成人精品一区二区| 日韩欧美一二三| 狠狠精品干练久久久无码中文字幕| 美女隐私在线观看| 亚洲激情五月婷婷| 日韩av中文字幕在线播放| 超碰在线人人| 99久久国产综合精品女不卡| 亚洲精品国产一区| 你懂的国产精品| av资源站久久亚洲| 99精品小视频| 最新国产の精品合集bt伙计| 国产一区二区三区在线观看精品 | 理论视频在线观看| 伊人成人在线视频| 777亚洲妇女| 91精品视频在线播放| 国产精品一区二区中文字幕| 亚洲国产精品久久一线不卡| 成人伊人222| 欧美日韩亚洲视频| 成人在线播放免费观看| av国产在线观看| 欧美日韩三区四区| 国产69精品久久久久9999apgf | 樱桃视频成人在线观看| 日韩精品中文字幕一区| 黄色在线看片| 精品香蕉一区二区三区| 草民电影神马电影一区二区| 久久久91精品国产| 亚洲bt欧美bt精品777| 波多野结衣久草一区| 丝袜美腿亚洲综合| heyzo亚洲| 不卡的av中国片| 在线播放色视频| 欧美一级欧美三级| a级日韩大片| 日韩福利一区二区三区| 丝袜脚交一区二区| 黄色三及免费看| 欧美变态tickling挠脚心| 亚洲成人精品综合在线| 国产精品久久久久久亚洲影视 | 日本免费成人| 人人澡人人澡人人看欧美| 国产日韩一区| 久久久久久久少妇| 日韩女优制服丝袜电影| 玖玖玖视频精品| 杨幂一区欧美专区| 国产精品传媒入口麻豆| 亚洲电影视频在线| 欧美激情在线一区| 亚洲一区二区三区午夜| **欧美大码日韩| 日韩av中字| 2019av中文字幕| 国产精品18久久久久久久网站| 亚洲精品少妇久久久久久| 综合久久五月天| 国产在线精品国自产拍免费| 97超碰人人澡| 亚洲国产成人精品女人久久久 | 精品久久久久中文字幕小说 | 欧美精品aaaa| 黑人巨大精品欧美一区二区一视频| 99re6热只有精品免费观看| 久久福利一区二区| 国产一区二区久久精品| 日韩在线一区二区| youjizz在线播放| 91九色露脸| 欧美日韩国产综合一区二区三区 | 国产探花一区二区| 国产性xxxx18免费观看视频| 精品无人国产偷自产在线| 免费看成人哺乳视频网站| 老司机午夜激情| 欧洲精品在线播放| 91久久精品日日躁夜夜躁欧美| 欧美色图在线播放| 欧美三级一级片| 日韩在线视频导航| 国产日韩精品视频一区| 午夜av成人| 亚洲国产精品美女| 国产成人无码精品久久久性色| 亚洲网址你懂得| 国产精品午夜免费| av亚洲免费| 欧美13一16娇小xxxx| 在线观看亚洲视频啊啊啊啊| 在线亚洲男人天堂| 国产精品国产自产拍高清av| 99久久精品一区二区成人| xxxx一级片| 国产伦精品一区二区三区四区免费 | 三级黄视频在线观看| 欧州一区二区三区| 日韩视频免费直播| 成人午夜视频在线| 999精品视频| 8x8ⅹ拨牐拨牐拨牐在线观看| 久久手机在线视频| 992tv成人免费视频| 一区二区三区精品在线| 成人福利片网站| 国产欧美日韩麻豆91| 国产精品久久久久9999赢消| 男人资源在线播放| 国产成人亚洲精品无码h在线| 日本欧美一级片| 亚洲美女性视频| 亚洲电影有码| 特黄特色特刺激视频免费播放| 国产精品扒开腿做爽爽爽视频| 亚洲精品美女在线| 欧美日韩一区二区在线播放| 日日夜夜一区二区| 精品99在线| 美国十次综合久久| 僵尸再翻生在线观看| 在线看的你懂得| 天堂中文字幕一二区| 免费成人在线视频网站| 日韩高清专区| 91色琪琪电影亚洲精品久久| 精品中文字幕视频| 亚洲的天堂在线中文字幕| 欧美日韩国产丝袜美女| 最新不卡av在线| 亚洲国产电影在线观看| 久久免费电影网| 欧美韩国日本综合| 99久久久久久| 久久综合狠狠综合| 懂色av一区二区三区蜜臀| 国产91精品免费| 99久久精品国产毛片| av一本久道久久综合久久鬼色| 蜜臀99久久精品久久久久久软件| 欧美 日韩 国产 一区| 国产欧美欧美| 日韩视频一区| 精彩视频一区二区三区| 国产激情一区二区三区四区| 韩国午夜理伦三级不卡影院| 一个色综合导航| 日韩欧美在线免费观看| 国产69精品久久久久按摩| 日本综合字幕| 91久久精品一区二区三区| 久久精品亚洲国产奇米99| 午夜亚洲影视| 日韩不卡一区二区三区| 免费在线成人网| 国产精品久久久久久久久久免费看| 亚洲素人一区二区| 欧美在线高清视频| 欧美精品成人一区二区在线观看| 宅男噜噜噜66一区二区66| 日韩午夜中文字幕| 7878成人国产在线观看| 在线成人一区二区| 国产亚洲一区二区三区四区| 黄色网址在线免费播放| 免费看a在线观看| 成人日韩精品| 国产精品对白| 日韩电影在线看| av在线不卡网| 亚洲激情校园春色| 亚洲精品久久久久国产| 精品一区二区三区四区| 国产美女搞久久| 日韩av资源在线| 黄色在线播放| 日韩三级网址| 围产精品久久久久久久| 成人av在线影院| 正在播放一区二区| 日韩av不卡在线| 国产aaa一级片| 电影网一区二区| 日韩vs国产vs欧美| 日韩欧美aaa| 午夜精品一区二区三区在线视频| 亚洲日本一区二区三区在线不卡| 国外男同性恋在线看| 亚洲精品在线观看www| 成人做爰www免费看视频网站| 欧美亚洲视频一区| 性网站在线播放|