java - 在对象上调用 setter 后安全发布 Java 对象

标签 java multithreading

在构造函数执行后但在返回引用之前调用 setter 是否是安全的发布?

public class SafePublication {
    private int i = 0;
    private SafePublication() {
            i = 10;
    }

    // Here we are calling setter are object creation. 
    //Will this change be visible to other threads
   public static SafePublication getInstance() {
           SafePublication pub = new SafePublication();
           pub.setVal(20);
           return pub;
   }

   private void setVal(int x) {
           this.i = x;
   }
}

最佳答案

不,这不安全。

setVal 方法不是同步的,i 不是易变的。因此,在对 i 的更新(通过 setVal)与在读取 i 的另一个线程上运行的任何代码之间将没有同步点。 setVal 调用发生在构造实例的线程中这一事实产生了不同。

最重要的是,另一个线程可能i的值视为010中的任何一个> 或 20


How may another thread see that value if the reference to the object has not been returned yet?

事实并非如此。问题是其他线程可能看不到i的正确值。

我认为您将这种情况与字段为 final 的情况混淆了。在那里,JLS 确实指定该字段已安全发布。问题在于此保证不适用于非最终字段;见JLS 17.5 .写法如下:

"An object is considered to be completely initialized when its constructor finishes. A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields. "

(强调)


i would rather say another thread may see the value of i as any one of 10 or 20. It is guaranteed not to see 0.

据我所知,JLS 17.4 中没有任何内容或 JLS 17.5提供保证。唯一可以保证的是,在默认初始化发生之前,没有人会看到 i 的值。 (请随意证明我错了......引用 JLS。)

关于java - 在对象上调用 setter 后安全发布 Java 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14120712/

相关文章:

java - 如何组装 SBT Scala 库以包含在 Java 7 Maven 项目中?

c# - Windows 服务内存使用量增加

java - 在工作线程中读取 GUI 对象数据

c++ - std::lock() 相当于 boost::shared_mutex?

c++ - 使用 make_shared<std::thread> 创建 shared_ptr<std::thread> 的实例

objective-c - 为什么我的 GCD 方法没有响应?

java - 如何将 JColorChooser 添加到内容 Pane /Jpanel?

java - 如何将RGB图像转换为CIELUV色彩空间?

java - Spring中抛出404并重定向到自定义错误页面

java - 使用 stringtokenizer 来统计单词问题