Val*_*ous 11 java concurrency hashmap concurrenthashmap java-8
我正在计算电子选举的选票,并且在我的初始版本中我只有一个政党。每个选民将有不同的线程,线程将更新给定政党的选票计数。
我决定使用 ConcurrentHashMap,但结果不是我所期望的......
Map<String, Integer> voting = new ConcurrentHashMap<>();
for (int i = 0; i < 16; i++) {
new Thread(() -> {
voting.put("GERB", voting.getOrDefault("GERB", 0) + 1);
}).start();
}
for (int i = 0; i < 100; i++) {
voting.put("GERB", voting.getOrDefault("GERB", 0) + 1);
}
Thread.sleep(5000); // Waits for the threads to finish
for (String s : voting.keySet()) {
System.out.println(s + ": " + voting.get(s));
}
Run Code Online (Sandbox Code Playgroud)
结果每次都不一样——范围从 114 到 116。
ConcurrentHashMap 不应该同步吗?
Rav*_*ala 12
嗯,这里有一个复合动作。您获得给定键的映射值,将其递增 1,然后将其放回映射中的同一个键。您必须保证所有这些语句都以原子方式执行。但是给定的实现并没有强加这个先决条件。因此,您最终会遇到安全故障。
要解决此问题,您可以使用中merge定义的原子操作ConcurrentHashMap。整个方法调用以原子方式执行。这是它的外观。
Map<String, Integer> voting = new ConcurrentHashMap<>();
for (int i = 0; i < 16; i++)
new Thread(() -> {
voting.merge("GERB", 1, Integer::sum);
}).start();
for (int i = 0; i < 100; i++)
voting.merge("GERB", 1, Integer::sum);
Thread.sleep(5000); // Waits for the threads to finish
for (String s : voting.keySet())
System.out.println(s + ": " + voting.get(s));
Run Code Online (Sandbox Code Playgroud)
运行此程序会产生以下输出:
日耳曼语:116