Brian Goetz在http://www.ibm.com/developerworks/java/library/j-jtp03048.html上写了一篇关于fork-join的很好的文章。在其中,他列出了一种使用fork-join机制的合并排序算法,在该算法中,他并行地在数组的两侧执行排序,然后合并结果。
该算法同时对同一数组的两个不同部分进行排序。为什么不需要AtomicIntegerArray或其他机制来维护可见性?如何保证一个线程可以看到另一个线程完成的写操作,或者这是一个微妙的bug?接下来,Scala的ForkJoinScheduler是否也提供了这样的保证呢?
谢谢!
发布于 2011-01-26 09:34:28
(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写入时,在读取y之前发生的所有写入都是可用的。例如
public void doWork(){
x = 10;
y = 5;
}如果另一个线程读取y=5,则该线程将被保证读取x= 10。这是因为对y的写入创建了一个同步点,在该同步点之前的所有写入将在写入之后可见。
使用Fork Join池,ForkJoinTask的联接将创建一个同步点。现在,如果t2.fork()和t1.voke()结合在一起,t2将确保可以看到之前发生的所有写操作。由于之前的所有写入都在相同的结构中,因此它将是安全的。
如果这不是很清楚,我很乐意进一步解释。
发布于 2011-01-26 09:12:16
只需猜测一下: merge包含对Thread的连接,而连接保证了可见性。
第二部分是肯定的;我不知道merge是如何实现的。
https://stackoverflow.com/questions/4800503
复制相似问题