![](/img/trans.png)
[英]With double-checked locking, does a put to a volatile ConcurrentHashMap have happens-before guarantee?
[英]Why does ConcurrentHashMap work in Double Checked Locking
在“ Java Concurrency in Practice”一书中提到以下代码不是线程安全的:
@NotThreadSafe
public class DoubleCheckedLocking {
private static Resource resource;
public static Resource getInstance(){
if(resource == null){
synchronized (DoubleCheckedLocking.class){
if(resource == null)
resource = new Resource();
}
}
return resource;
}
}
它不是线程安全的,因为:-一个线程可以创建Resource的新实例-另一个线程在“ if”条件下同时不能获得空引用,但是Resource对象不会完全初始化
在这个问题上是类似的代码。 资源存储在concurentHashMap中,人们说它是threadSafe。 像这样:
public class DoubleCheckedLocking2 {
private static ConcurrentHashMap<String, ComplexObject> cache = new ConcurrentHashMap<String, ComplexObject>();
public static ComplexObject getInstance(String key) {
ComplexObject result = cache.get(key);
if (result == null) {
synchronized (DoubleCheckedLocking2.class) {
ComplexObject currentValue = cache.get(key);
if (currentValue == null) {
result = new ComplexObject();
cache.put(key, result);
} else {
result = currentValue;
}
}
}
return result;
}
}
为什么将值存储在ConcurrentHashMap中会使代码成为threadSafe ? 我认为ComplexObject仍可能不会完全初始化,并且此“部分对象”将保存在地图中。 其他线程将读取部分未完全初始化的对象。
我想我知道什么是“事前发生”,我已经分析了JDK 8.0_31中的代码,但我仍然不知道答案。
我知道诸如computeIfAbsent , putIfAbsent之类的功能。 我知道这段代码可以用不同的方式编写。 我只是不知道使该代码成为线程安全的细节。
实际上发生在这里才是关键。 边缘从map.put(key, object)
扩展到后续map.get(key)
之前发生了事情 ,因此,您检索的对象至少与存储在地图中的对象保持最新。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.