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"));

    }
}

  最终输出结果:

  

猜你喜欢

转载自www.cnblogs.com/cnxieyang/p/12766002.html