在《Java并发编程实战》一书中提到,以下代码不具备线程安全性:
为什么将值存储在ConcurrentHashMap中可以使代码线程安全?我认为,复杂对象可能不会完全初始化,这个“部分对象”将保存在映射中。其他线程将读取部分未完全初始化的对象。
我知道什么是“happens-before”,我已经分析了JDK 8.0_31中的代码,但我仍然不知道答案。
我知道像computeIfAbsent、putIfAbsent之类的函数,我知道可以以不同的方式编写此代码。我只想知道使此代码线程安全的详细信息。
@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对象可能没有完全初始化
在这个问题中有类似的代码。资源存储在ConcurrentHashMap中,并且人们说它是线程安全的。就像这样:
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中可以使代码线程安全?我认为,复杂对象可能不会完全初始化,这个“部分对象”将保存在映射中。其他线程将读取部分未完全初始化的对象。
我知道什么是“happens-before”,我已经分析了JDK 8.0_31中的代码,但我仍然不知道答案。
我知道像computeIfAbsent、putIfAbsent之类的函数,我知道可以以不同的方式编写此代码。我只想知道使此代码线程安全的详细信息。