java - 为什么 ConcurrentHashMap 在 Double Checked Locking 中工作

标签 java multithreading 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;
    }
}

它不是线程安全的,因为: - 一个线程可以创建新的资源实例 - 在“if”条件下,另一个线程同时获得非空引用,但 Resource 的对象将不会被完全初始化

在此question是类似的代码。资源存储在 concurentHashMap 中,人们说它是线程安全的。像这样:

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 中使代码线程安全?我认为 ComplexObject 仍然有可能不会完全初始化并且这个“部分对象”将保存在 map 中。其他线程将读取部分未完全初始化的对象。

我想我知道什么是“happens-before”,我已经分析了 JDK 8.0_31 中的代码,但我仍然不知道答案。

我知道 computeIfAbsentputIfAbsent 等函数。我知道这段代码可以用不同的方式编写。我只是想知道使这段代码线程安全的细节。

最佳答案

Happens before 实际上是这里的关键。从 map.put(key, object) 延伸到后续的 map.get(key) 有一个happens before 边,因此你的对象retrieve 至少与存储在 map 中时一样最新。

关于java - 为什么 ConcurrentHashMap 在 Double Checked Locking 中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28951716/

相关文章:

java - 在局部变量上同步是否合理?

c# - 如何查看用第二个线程显示的对话框的 Windows 消息?

java - volatile 读取冲突

java - 在按钮操作上将背景图像添加到 JPanel

java - Android截击奇怪的错误

具有等待时间的 pthreads 的消费者/生产者

PHP线程和同步

java - 无法将 libGDX 项目导入 Eclipse。

java - 树单元渲染器 : applying different style of the node's text which is depending on the user object's type

objective-c - 迈克阿什辛格尔顿 : Placing @synchronized