Java内存模型是否为线程池交互提供happens-before保证?具体而言,线程池工作线程在运行完工作队列中的项目之前所做的写入是否对运行该队列下一个项目的工作线程可见?
规范(我个人认为这个FAQ很有用:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#synchronization)指出:“对线程调用start()发生在启动的线程中的任何操作之前。”或者简单地说,在启动线程之前进行的任何内存写入都将在启动的线程执行的run()方法之前被执行并且可见。但是对于线程池来说,start()通常会在你进行写入之前运行。考虑一个简单的工作流,其中上下文对象被改变并传递到下一个操作:
规范(我个人认为这个FAQ很有用:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#synchronization)指出:“对线程调用start()发生在启动的线程中的任何操作之前。”或者简单地说,在启动线程之前进行的任何内存写入都将在启动的线程执行的run()方法之前被执行并且可见。但是对于线程池来说,start()通常会在你进行写入之前运行。考虑一个简单的工作流,其中上下文对象被改变并传递到下一个操作:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
private static class Container<T> {
private T value;
public T get() {
return value;
}
public void set(T newValue) {
value = newValue;
}
}
public static void main(String[] args) {
final Container<Integer> sharedObject = new Container<>();
final ExecutorService executor = Executors.newFixedThreadPool(10);
// SKIPPED: pre-warm the executor so all worker threads are start()'ed
final Runnable read = () -> System.out.println("Got " + sharedObject.get());
Runnable write = () -> {
sharedObject.set(35);
executor.execute(read);
};
executor.execute(write);
// SKIPPED: wait until done
}
}
< p > write.run()
对 sharedObject.value
的写入能够被 read.run()
所看到吗?(不是询问顺序,这是显而易见的)
(PS:我知道将 value
设为 volatile
可以提供这个保证)
更新(补充回答):
java.util.concurrent
包的摘要文档总结了语言提供并由框架扩展的内存一致性保证:https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility
sharedObject.set(35)
和println
之间肯定存在hb关系。也许你错过了第二个任务是从第一个任务中添加到队列中的这一事实,而不是在主线程中添加的。 - assylias