Видимость памяти в Fork-join - PullRequest
6 голосов
/ 26 января 2011

Брайан Гетц написал отличную статью о fork-join на http://www.ibm.com/developerworks/java/library/j-jtp03048.html.. В нем он перечисляет алгоритм сортировки слиянием с использованием механизма fork-join, в котором он выполняет сортировку по двум сторонам массива параллельно. , затем объединяет результат.

Алгоритм сортирует два разных раздела одного и того же массива одновременно. Почему не AtomicIntegerArray или какой-либо другой механизм, необходимый для поддержания видимости? Какая гарантия, что один поток увидит записи, сделанные другим, или это неуловимая ошибка? В качестве продолжения, Scala's ForkJoinScheduler также дает эту гарантию?

Спасибо!

Ответы [ 2 ]

6 голосов
/ 26 января 2011

Соединение (из 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.invoke (), соединение t2 гарантирует, что все записи, которые произошли ранее, будут видны. Поскольку все предыдущие записи находятся в одной структуре, они будут безопасны для видимости.

Я был бы рад объяснить, если это не так ясно.

1 голос
/ 26 января 2011

Просто предположение: слияние включает в себя присоединение к потоку, и объединение гарантирует видимость.

Вторая часть уверена;Я не знаю, как осуществляется слияние.

...