Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 构造的非最终字段和内部可运行/线程可见性_Java_Multithreading_Visibility_Happens Before - Fatal编程技术网

Java 构造的非最终字段和内部可运行/线程可见性

Java 构造的非最终字段和内部可运行/线程可见性,java,multithreading,visibility,happens-before,Java,Multithreading,Visibility,Happens Before,我想这与“先发生后发生”规则有关,但我没有具体的解释。。。 我的问题是,如果非finalfield引用“helloworld”保证被线程“Thread”看到? 不,我不想让nonFinalField成为final,它不会在以后更新,因为也没有允许它的方法 希望我们能用一个合理的解释来揭开这个例子的神秘面纱 先谢谢你 亲切问候,, 赫尔曼 由于在构造对象(因此完全初始化)之前无法调用startThread,因此该线程肯定会看到非final字段被初始化 但是,如果另一个线程在运行该线程之前设法查看它

我想这与“先发生后发生”规则有关,但我没有具体的解释。。。 我的问题是,如果非finalfield引用“helloworld”保证被线程“Thread”看到? 不,我不想让nonFinalField成为final,它不会在以后更新,因为也没有允许它的方法

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

先谢谢你

亲切问候,, 赫尔曼


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

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


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

是的,在
startThread
中启动的线程保证可以看到
nonFinalField
的值,因为启动线程会在父线程(调用主线程的线程)和子线程之间建立“发生在”的关系(线程在
开始线程
中启动)


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

据我所知,它将是可见的。使用java.util.concurrent包javadoc中的“之前发生”关系规则:

  • 线程中的每个动作都发生在该线程中的每个动作之前,该线程中的每个动作都是按照程序的顺序稍后出现的
  • 对线程的启动调用发生在已启动线程中的任何操作之前
因为before是可传递的,这意味着“ThreadA中调用ThreadB.start()之前的每个操作都发生在ThreadB中的每个操作之前”


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

构造不会建立“之前发生”的关系。您可以详细说明第二句话吗?@user2050516-例如,如果不使用局部变量,则(正如您在示例中所做的)如果使用对象中的
static
变量,则另一个线程很可能会看到
static
变量包含尚未初始化的实例变量的对象。
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();
    }
}