ConcurrentHashMap 線程不安全


本文闡述ConcurrentHashMap線程安全問題,ConcurrentHashMap可以保證多線程讀寫操作時的安全,實際代碼使用時,可能會有以下誤區,從下面的實例代碼中進行演示。

兩個線程分別進行++操作,總共加2000次,核對輸出結果是否是2000;

有誤區的實例代碼

  實例代碼如下所示。

  

package com.yang.concurrent;

import java.util.concurrent.ConcurrentHashMap;

/**
 * 錯誤使用ConcurrentHashMap
 */
public class ErrorUseConcurrentHashMap implements Runnable {
    private static ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

    /**
     * 這種寫法會導致多線程情況下value是線程不安全的,和ConcurrentHashMap無關
     */
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            int value = map.get("tom");
            value++;
            map.put("tom", value);
        }

    }

    public static void main(String[] args) throws InterruptedException {
        map.put("tom", 0);
        ErrorUseConcurrentHashMap errorUseConcurrentHashMap = new ErrorUseConcurrentHashMap();
        Thread thread1 = new Thread(errorUseConcurrentHashMap);
        Thread thread2 = new Thread(errorUseConcurrentHashMap);
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println("最終輸出值:" + map.get("tom"));

    }
}

  輸出結果如下圖:

  

 

 

正確的實例代碼

  實例代碼如下圖,我們將上述的代碼優化下。使用CAS的操作方式對其進行優化。

  

package com.yang.concurrent;

import java.util.concurrent.ConcurrentHashMap;

/**
 * 正確使用ConcurrentHashMap
 */
public class CorrectUseConcurrentHashMap implements Runnable {
    private static ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

    /**
     * 此處我們使用CAS操作方式,來替換Synchronized,提供效率
     */
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            while (true){
                int oldValue = map.get("tom");
                int newValue=oldValue+1;
                boolean flag=map.replace("tom",oldValue,newValue);
                if (flag){
                    break;
                }
            }
        }

    }

    public static void main(String[] args) throws InterruptedException {
        map.put("tom", 0);
        CorrectUseConcurrentHashMap errorUseConcurrentHashMap = new CorrectUseConcurrentHashMap();
        Thread thread1 = new Thread(errorUseConcurrentHashMap);
        Thread thread2 = new Thread(errorUseConcurrentHashMap);
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println("最終輸出值:" + map.get("tom"));

    }
}

  最終輸出結果:

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM