java在处理并发哈希映射时必须使用锁
下面是我的一个类中的代码:
class SomeClass {
private Map<Integer, Integer> map = new ConcurrentHashMap<>();
private volatile int counter = 0;
final AtomicInteger sum = new AtomicInteger(0); // will be used in other classes/threads too
private ReentrantLock l = new ReentrantLock();
public void put(String some) {
l.lock();
try {
int tmp = Integer.parseInt(some);
map.put(counter++, tmp);
sum.getAndAdd(tmp);
} finally {
l.unlock();
}
}
public Double get() {
l.lock();
try {
//... perform some map resizing operation ...
// some calculations including sum field ...
} finally {
l.unlock();
}
}
}
您可以假设这个类将在并发环境中使用
问题是:你认为锁的必要性是什么?这段代码闻起来怎么样?:)
# 1 楼答案
让我们看看
public void put(String some)
中的操作map.put(counter++, tmp);
sum.getAndAdd(tmp);
现在让我们看一下各个部分
counter
是一个易变变量。因此,它只提供内存可见性,而不提供原子性。因为counter++
是一个复合操作,所以需要一个锁来实现原子性map.put(key, value)
是原子的,因为它是ConcurrentHashMap
sum.getAndAdd(tmp)
是原子的,因为它是AtomicInteger
李>如您所见,除了
counter++
之外,其他所有操作都是原子操作。然而,您正试图通过组合所有这些操作来实现某些功能。要在功能级别实现原子性,需要一个锁。这将帮助您避免线程在各个原子操作之间交错时产生意外的副作用所以你需要一个锁,因为
counter++
不是原子的,你需要结合一些原子操作来实现一些功能(假设你希望它是原子的)