Java中的ConcurrentHashMap和AtomicInteger示例

时间:2018-02-02 01:12:11

标签: java multithreading nonblocking concurrenthashmap atomicinteger

我正在尝试实现以下功能: str数组中的每个键都应该与一个从0开始并存储在map中的Integer相关联。执行后,映射应包含str中的所有键,并且计数应与最终值9一致。但结果从8到12不等。我做错了什么?

import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class Main {

public static final ConcurrentMap<String, Integer> map = new ConcurrentHashMap<>();
public static final AtomicInteger count = new AtomicInteger(0);
public static final String[] str = {
    "a", "b", "c", "d", "e", "f", "g", "h"
};

public static void main(String[] args) throws InterruptedException {
    for (int i = 0; i < 10; i++) {
        ExecutorService exe = Executors.newFixedThreadPool(4);
        for (int j = 0; j < 100; j++) {
            exe.execute(() -> {
                for (int k = 0; k < 1000; k++) {
                    int index = k % 8;
                    String key = str[index];
                    Integer value = map.get(key);
                    if (value == null) {
                        Integer next = count.incrementAndGet();
                        map.putIfAbsent(key, next);
                    }
                }
            });
        }
        exe.shutdown();
        exe.awaitTermination(5, TimeUnit.SECONDS);
        System.out.println("count = " + count.get());
    }


}
}

1 个答案:

答案 0 :(得分:3)

你的竞争条件如下:

Integer value = map.get(key);   // read
if (value == null) {
    Integer next = count.incrementAndGet();
    map.putIfAbsent(key, next); // write
}

如果在读取之后和写入之前由另一个线程设置了密钥,则将执行incrementAndGet(),但实际上不会插入它,因为putIfAbsent()是原子的。您可以使用computeIfAbsent()

以原子方式对地图执行条件增量
map.computeIfAbsent(key, k -> count.incrementAndGet());