繁体   English   中英

Java内存模型发生在线程池交互的保证之前

[英]Java Memory Model happens-before guarantees for Thread Pool interactions

Java内存模型是否为Thread Pool交互提供了先前发生的保证? 特别是,在工作队列中运行项目结束之前由线程池工作线程进行的写入是否会在之后从队列中运行下一个项目的工作线程可见?

规范(我个人觉得这个常见问题解答很有用: http//www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#synchronization )声明“对a的调用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
    }
}

write.run()sharedObject.value的写入是否保证是可见的(不要询问排序,这很明显) read.run()

(PS:据我所知,使value volatile确实提供了这种保证)

更新(补充答案): java.util.concurrent软件包摘要文档总结了语言提供并由框架扩展的内存一致性保证: https//docs.oracle.com/javase/7/docs/api/java/ UTIL /并发/包summary.html#MemoryVisibility

我认为它保证是可见的。 ExecutorService延伸Executor ,和javadoc文档Executor说:

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

通过我的阅读,这与你的例子中的内容相符。 write runnable正在提交read runnable,因此在write线程(即set调用)中提交之前的事件与之后在read线程中的事件(即get调用)之间存在一个before-before关系。

write runnable本身提交的事实意味着在创建Container对象和set的调用之间也存在一个发生的事件

引用ExecutorService javadoc:

内存一致性效果:在向ExecutorService提交RunnableCallable任务之前的线程中的操作发生在该任务ExecutorService 任何操作之前 ,而该操作又发生在通过Future.get()检索结果之前

但是,它没有说明添加到队列中的两个任务,以及任务1的处理是否发生 - 在处理任务2之前,从任务中可以看出。 只有将任务添加到队列才会在任务处理之前发生,并且任务执行在原始调用者检索结果之前发生。

更新

在两个不同的,独立提交的任务之间没有发生 - 之前的相关性,即使以某种方式知道在另一个开始运行之前运行完成。

当然,当一个任务提交,好像是在问题后,在任务1所采取的任何行动将其提交任务2 之前发生-前任务2的执行。

如果任务1在提交任务2之后继续做其他事情,那么当然没有事先保证,因为任务2可以在任务1继续它的工作之前运行并完成。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM