繁体   English   中英

Fork-join中的内存可见性

[英]Memory visibility in Fork-join

Brian Goetz在http://www.ibm.com/developerworks/java/library/j-jtp03048.html上写了一篇关于fork-join的好文章。 在其中,他列出了使用fork-join机制的合并排序算法,在该机制中,他并行执行数组两侧的排序,然后合并结果。

该算法同时对同一阵列的两个不同部分进行排序。 为什么不是AtomicIntegerArray或维持可见性所需的其他机制? 什么保证一个线程会看到另一个线程完成的写入,或者这是一个微妙的错误? 作为后续跟进,Scala的ForkJoinScheduler是否也提供此保证?

谢谢!

(ForkJoin)的连接本身需要一个同步点,这是最重要的信息。 同步点将确保在所述点之后发生的所有写入都是可见的。

如果您查看代码,可以看到同步点出现的位置。 这只是调用invokeAll的一个方法

public static void invokeAll(ForkJoinTask<?> t1, ForkJoinTask<?> t2) {
    t2.fork();
    t1.invoke();
    t2.join();
}

这里t2分叉到另一个进程,t1执行它的任务,并且调用线程将在t2.join()上等待。 通过t2时。 然后,对t1和t2的所有写入都将可见。

编辑:这个编辑只是为了解释我对同步点的意义。

可以说你有两个变量

int x;
volatile int y;

任何时候你写y你读之前发生的所有写作都将可用。 例如

public void doWork(){
   x = 10;
   y = 5;
}

如果另一个线程读取y = 5,则保证线程读取x = 10.这是因为写入y会创建一个同步点,在该点之后,在写入之后所有写入之前的所有写入都将可见。

使用Fork Join池,ForkJoinTask的连接将创建一个同步点。 现在,如果t2.fork()和t1.invoke(),t2的加入将确保将看到之前发生的所有写入。 由于所有先前的写入都在相同的结构内,因此可见性是安全的。

如果不清楚,我会很乐意进一步解释。

只是一个猜测:merge包括加入一个Thread,并且join保证了可见性。

第二部分是肯定的; 我不知道如何实现合并。

暂无
暂无

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

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