Fork-join中的内存可见性 [英] Memory visibility in Fork-join

查看:300
本文介绍了Fork-join中的内存可见性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Brian Goetz's wrote a nice article on fork-join at http://www.ibm.com/developerworks/java/library/j-jtp03048.html. In it, he lists a merge sort algorithm using the fork-join mechanism, in which he performs the sort on two sides of an array in parallel, then merges the result.

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

The algorithm sorts on two different sections of the same array simultaneously. Why isn't an AtomicIntegerArray or some other mechanism necessary to maintain visibility? What guarantee is there that one thread will see the writes done by the other, or is this a subtly bug? As a follow up, does Scala's ForkJoinScheduler also make this guarantee?

谢谢!

推荐答案

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

The join (of ForkJoin) itself requires a synchronization point, thats the most important piece of information. A synchronization point will ensure that all writes that happen are visible after said point.

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

If you take a look at the code you can see where the synchronization point occurs. This is just one method call invokeAll

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

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

Here t2 forks into another process, t1 executes its task and that calling thread will wait on t2.join(). When passing t2. All writes to t1 and t2 will then be visible.

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

This edit is just to give a little more of an explanation of what I meant by synchronization point.

假设你有两个变量

int x;
volatile int y;

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

Any time you write to y all writes that happened before you read y will be available. For example

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

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

If another thread reads y = 5 that thread is guaranteed to read x = 10. This is because the write to y creates a synchronization point in which all writes before said point will be visible after the write.

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

With the Fork Join pool the join of a ForkJoinTask will create a synchronization point. Now if t2.fork() and t1.invoke() the joining of t2 will ensure that all writes that previously happened will be seen. Since all the previous writes are within the same structure it will be safe for visibility.

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

I would be happy to explain further if that isnt as clear.

这篇关于Fork-join中的内存可见性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆