请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

ConcurrentHashMap的问题?

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?

正在回答 回答被采纳积分+3

1回答

Jimin 2018-10-17 01:03:18
你好,这个是典型的“先判断后执行”问题,需要让 判断和执行原子执行就可以,就是保证这里get和put操作之间不能因为其他线程影响执行了其他的对map更新的指令,不加 synchronized的话,就需要对“先判断后执行”的部分加其他的锁,比如ReentrantLock。 
0 回复 有任何疑惑可以回复我~
  • 提问者 北斗神拳1984 #1
    除了Atomic包和synchronized的关键字是原子性的,并发容器的操作也是原子性的吗?
    回复 有任何疑惑可以回复我~ 2018-10-17 09:21:47
  • Jimin 回复 提问者 北斗神拳1984 #2
    jdk提供的并发容器提供的单个功能都是线程安全的,但是如果两个一起使用就不一定线程安全了。因为他们之间已经可以插入其他操作了,因此对于这种先检查再执行的操作,要保证原子执行,都是需要加锁的。
    回复 有任何疑惑可以回复我~ 2018-10-17 09:30:16
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信