java - 设置这个引用线程安全吗?

标签 java multithreading

关于这段代码是否是线程安全的,我总是得到不同的答案。我正在使用 Java 8。

private final Object lock = new Object();
private volatile Object reference = null;

public Object getOrCompute(Supplier<Object> supplier) {
    if (reference == null) {
        synchronised(lock) {
            if (reference == null) {
                reference = supplier.get();
            }
        }
    }

    return reference;
}

我的期望是,给定此类的新实例,多次调用 getOrCompute() 只会导致调用一个供应商,并且该供应商的结果是所有调用的结果(和 future 的调用)到 getOrCompute()

最佳答案

这是安全的,因为在 supplier.get() 中所做的任何事情都不能通过分配给 reference 来重新排序。 (或者更准确地说,当您对 reference 进行 volatile 读取时,它不能显示为重新排序。)

锁提供排他性,可变的写/读语义提供可见性。请注意,自很久以前发布的 Java 5 以来,这一直是正确的,但您仍然会在 Internet 上找到关于双重检查锁定(因为这是这个习语的正式名称)如何过时的文章。工作。它们在当时是正确的,但现在已经过时了。

如果供应商本身提供可变对象,则可能不安全。但那是另一回事。

关于java - 设置这个引用线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31244967/

相关文章:

java - HTTP 错误 404 请求的资源不可用,Glassfish

java - bitbucket 如何将 bug # 附加到提交的消息中

.net - .NET上的线程安全阻止队列实现

C#静态方法问题

java - 如何关闭小程序内的框架?

java - 删除给定节点上的 XML 内容并重新排列输出文件格式

java - 我无法修复我在代码中遇到的错误,我猜我下载了所有需要的 Jar 文件

multithreading - Mac 允许的最大线程数

java - 使用 queueEvent() 在渲染器和另一个类之间传递变量

java - 为线程编写一个舒适的暂停/停止方法