在Java中赋值给变量的可见性

Mar*_*c G 8 java concurrency multithreading

我最近和一位朋友就这样的代码争论过:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
 * See memory consistency effects in a Java Executor.
 */
public class PrivateFieldInEnclosing {
    private long value;
    PrivateFieldInEnclosing() {}
    void execute() {
        value = initializeValue();
        ExecutorService executor = Executors.newCachedThreadPool();
        executor.submit(new Y());
    }

    class Y implements Runnable {
        @Override
        public void run() {
            System.out.println(value);
        }
    }

    private long initializeValue() {
        return 20;
    }

    public static void main(String[] args) {
        new PrivateFieldInEnclosing().execute();
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为,这是可能的,value可以为可见0Y,因为有不能保证分配value = initializeValue()是在执行程序的线程是可见的.我说他需要做value一个不稳定的领域.

他与我发生矛盾,并说因为它是一个私有实例字段,在创建线程之前赋值,所以该值是可见的.

我查看了https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4但我无法确定我可以用作支持我的内容声明.谁能帮我?谢谢!

Ser*_*nov 10

它是否私有无关紧要.与此相关的是:

内存一致性效果:在将Runnable对象提交给Executor之前,线程中的操作发生在执行开始之前,可能在另一个线程中.

来自Executor文档.这意味着无论你在调用之前做什么都在submitrunnable中可见.您甚至可以在构造执行程序之后执行此操作,并且在此特定情况下,执行线程实际启动时甚至无关紧要,因为该submit方法本身提供了非常强大的保证.

这是使java.util.concurrent包非常有用的功能之一.