ConcurrentHashMap的问题?

来源:5-8 并发容器及安全共享策略总结

北斗神拳1984

2018-10-16

public class ConcurrentHashMapExample2 {

//请求总数
public static int clientTotal = 5000;

//同时并发执行的线程数
public static int threadTotal = 200;

private static Map<String,Integer> map = new ConcurrentHashMap<>();

public static void main(String[] args) throws Exception{
    ExecutorService executorService = Executors.newCachedThreadPool();
    final Semaphore semaphore = new Semaphore(threadTotal);
    final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
    final String key = "key";
    for (int i=0;i<clientTotal;i++){

        executorService.execute(() ->{
            try {
                semaphore.acquire();
                add(key);
                semaphore.release();
            } catch (Exception e) {
                log.error("exception",e);
            }
            countDownLatch.countDown();
        });
    }
    countDownLatch.await();//保证减少到0
    executorService.shutdown();
    log.info("size:{}", map.get(key));
}

private static void add(String key){
    Integer value = map.get(key);
    if (value == null) {
        map.put(key, 1);
    } else {
        map.put(key, value + 1);
    }
}

}
我能知道线程不安全的原因是判空的地方有问题,但是应该怎么改才能变成线程安全的,除了在方法上加synchronized?

写回答

1回答

Jimin

2018-10-17

你好,这个是典型的“先判断后执行”问题,需要让 判断和执行原子执行就可以,就是保证这里get和put操作之间不能因为其他线程影响执行了其他的对map更新的指令,不加 synchronized的话,就需要对“先判断后执行”的部分加其他的锁,比如ReentrantLock。 
0
2
Jimin
回复
北斗神拳1984
jdk提供的并发容器提供的单个功能都是线程安全的,但是如果两个一起使用就不一定线程安全了。因为他们之间已经可以插入其他操作了,因此对于这种先检查再执行的操作,要保证原子执行,都是需要加锁的。
2018-10-17
共2条回复

Java高并发编程,构建并发知识体系,提升面试成功率

构建完整并发与高并发知识体系,倍增高薪面试成功率!

3923 学习 · 832 问题

查看课程