Для соединения (из 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;
Каждый раз, когда вы пишете у всех пишет, что произошло, прежде чем читать у будет доступен. Например
public void doWork(){
x = 10;
y = 5;
}
Если другой поток читает у = 5, что нить гарантируется для чтения х = 10. Это потому, что записи в у создает точку синхронизации, в которой все операции записи перед указанной точкой будет видимый после записи.
С помощью вилки Join pool объединение ForkJoinTask создаст точку синхронизации. Теперь, если t2.fork() и t1.invoke(), объединение t2 будет гарантировать, что все записи, которые ранее произошли, будут видны. Поскольку все предыдущие записи находятся в одной структуре, это будет безопасно для видимости.
Я был бы рад объяснить, если это не так ясно.
Они работают на разных участках массива. Там нет споров, пока не произойдет слияние. –
Я согласен, что они работают на разных разделах. Но семантика модели памяти Java более или менее говорит о том, что не все потоки гарантированно будут видеть все записи (если переменная нестабильна). Согласно этому блогу: http://jeremymanson.blogspot.com/2009/06/volatile-arrays-in-java.html даже использование volatile int [] недостаточно, чтобы гарантировать, что другие потоки видят вашу запись в массив –