我可以将 ConcurrentHashMap 与 Integer 一起用于线程安全计数器吗?
Can I use ConcurrentHashMap with Integer for thread safe counters?
我想要几个柜台,我可以通过名称来解决。所以,我可以这样实现:
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.computeIfAbsent("key", k -> new Integer(0));
map.computeIfPresent("key", (k, v) -> v + 1);
它的代码是线程安全的吗?
我认为是的,因为ConcurrentHashMap
我们有同步访问,并且设置新引用也是线程安全操作。其他线程会因为安全发布而看到此更改,当我们在 ConcurrentHashMap
.
中保留存储桶锁时会发生这种情况
假设第一个语句 map.computeIfAbsent("key", k -> new Integer(0));
发生在 "initialization time",然后有一堆线程执行形式 map.computeIfPresent("key", (k, v) -> v + 1);
的调用,是的,算法将是正确的(我明白你的意思了吗?)。
JDK 的最新版本保证调用 ConcurrentHashMap.computeIfPresent()
不仅会调用以线程安全方式传入的表达式,它还会保证如果其他线程试图对同时使用相同的密钥,它们将阻塞并排队,这样所有的突变都会按顺序发生(这在分布式系统的术语中称为可串行化)。
是的,它是线程安全的,你可以测试一下:
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadsafeExample {
public static void main(String[] args) throws Exception {
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
int count = 1000;
AtomicInteger doneTasks = new AtomicInteger();
Thread[] threads = new Thread[count];
for(int i = 0 ; i < threads.length ; ++i) {
threads[i] = new Thread(() -> {
map.computeIfAbsent("key", k -> new Integer(0));
map.computeIfPresent("key", (k, v) -> v + 1);
doneTasks.incrementAndGet();
});
}
for(int i = 0 ; i < threads.length ; ++i)
threads[i].start();
while (doneTasks.get() < count)
Thread.sleep(3);
System.out.println("we expected count of key is: " + count + ", and we get: " + map.get("key"));
}
}
输出:
we expected count of key is: 1000, and we get: 1000
您可以替换:
map.computeIfAbsent("key", k -> new Integer(0));
map.computeIfPresent("key", (k, v) -> v + 1);
来自
map.compute("key", (k, v) -> v == null ? 1 : v + 1);
我想要几个柜台,我可以通过名称来解决。所以,我可以这样实现:
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.computeIfAbsent("key", k -> new Integer(0));
map.computeIfPresent("key", (k, v) -> v + 1);
它的代码是线程安全的吗?
我认为是的,因为ConcurrentHashMap
我们有同步访问,并且设置新引用也是线程安全操作。其他线程会因为安全发布而看到此更改,当我们在 ConcurrentHashMap
.
假设第一个语句 map.computeIfAbsent("key", k -> new Integer(0));
发生在 "initialization time",然后有一堆线程执行形式 map.computeIfPresent("key", (k, v) -> v + 1);
的调用,是的,算法将是正确的(我明白你的意思了吗?)。
JDK 的最新版本保证调用 ConcurrentHashMap.computeIfPresent()
不仅会调用以线程安全方式传入的表达式,它还会保证如果其他线程试图对同时使用相同的密钥,它们将阻塞并排队,这样所有的突变都会按顺序发生(这在分布式系统的术语中称为可串行化)。
是的,它是线程安全的,你可以测试一下:
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadsafeExample {
public static void main(String[] args) throws Exception {
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
int count = 1000;
AtomicInteger doneTasks = new AtomicInteger();
Thread[] threads = new Thread[count];
for(int i = 0 ; i < threads.length ; ++i) {
threads[i] = new Thread(() -> {
map.computeIfAbsent("key", k -> new Integer(0));
map.computeIfPresent("key", (k, v) -> v + 1);
doneTasks.incrementAndGet();
});
}
for(int i = 0 ; i < threads.length ; ++i)
threads[i].start();
while (doneTasks.get() < count)
Thread.sleep(3);
System.out.println("we expected count of key is: " + count + ", and we get: " + map.get("key"));
}
}
输出:
we expected count of key is: 1000, and we get: 1000
您可以替换:
map.computeIfAbsent("key", k -> new Integer(0));
map.computeIfPresent("key", (k, v) -> v + 1);
来自
map.compute("key", (k, v) -> v == null ? 1 : v + 1);