【问题标题】:constructed nonFinalField and inner Runnable/Thread visibility构造 nonFinalField 和内部 Runnable/Thread 可见性
【发布时间】:2013-10-21 13:41:52
【问题描述】:

我想这与发生前发生的规则有关,但我没有具体的解释...... 我的问题是,是否保证线程“线程”可以看到对“Hello World”的 nonFinalField 引用? 不,我不想让 nonFinalField 成为最终的,以后也不会更新,因为也没有允许它的方法。

希望我们可以用合理的解释来揭开这个例子的神秘面纱。

提前谢谢你。

亲切的问候, 赫尔曼

public class Test2 {

    private String nonFinalField;

    public Test2() {

        nonFinalField="Hello World";
    }

    void startThread() {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("nonFinalField: " + nonFinalField);
            }
        });
        thread.start();
    }

    public static void main(String[] args) {
        Test2 test = new Test2();
        test.startThread();
    }
}

【问题讨论】:

    标签: java multithreading visibility happens-before


    【解决方案1】:

    是的,在startThread 启动的线程保证可以看到nonFinalField 的值,因为启动线程会在父线程(调用 main 的线程)和子线程(在startThread)。

    这在17.4.4(第三个项目符号)的语言规范中列出。

    【讨论】:

      【解决方案2】:

      由于在构造对象(因此完全初始化)之前无法调用startThread,因此该线程肯定会看到已初始化的非最终字段。

      但是,如果另一个线程在线程运行之前设法查看它,则其他线程可能会看到未初始化的字段。

      请记住,可以通过反射查看私有字段。

      【讨论】:

      • 构造没有建立“发生在之前”的关系。
      • 能否详细说明第二句?
      • @user2050516 - 例如,如果不使用局部变量(如您在示例中所做的那样),而是使用对象中的 static 变量,则另一个线程很可能会看到static 变量包含一个具有尚未初始化的实例变量的对象。
      【解决方案3】:

      据我了解,它将是可见的。使用 java.util.concurrent 包 javadoc 中的“happens-before”关系规则:

      • 线程中的每个动作都发生在该线程中的每个动作之前
      • 在线程上启动的调用发生在已启动线程中的任何操作之前。

      由于happens-before 是可传递的,这意味着'在调用ThreadB.start() 之前ThreadA 中的每个动作都发生在ThreadB 中的每个动作之前'。

      因此,如果 ThreadA 是您的主线程,而 ThreadB 是您明确创建的线程,那么在启动第二个线程之前主线程中的事件将是可见的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-07-02
        • 1970-01-01
        • 1970-01-01
        • 2016-02-21
        • 2012-09-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多