видимость побочных эффектов при создании и присоединении потоков - PullRequest
4 голосов
/ 07 июня 2011

Когда записи, которые выполняются одним потоком, видны другому потоку, когда нет синхронизированных блоков и энергозависимых переменных?Вот упрощенный пример быстрой сортировки:

int middle = partitionForTheFirstTime(array);

Thread t = new Thread(new Quicksorter(array, 0, middle - 1));
Thread u = new Thread(new Quicksorter(array, middle + 1, array.size - 1));

t.start()
u.start();

t.join();
u.join();

(Ради простоты предположим, что два «рабочих потока» не порождают никаких дополнительных потоков.)

Объединяется ли с двумяпотоки гарантируют, что текущий поток видит все их побочные эффекты?


Что касается связанной ноты, что произойдет, если я создаю потоки до первоначального разбиения?

Quicksorter a = new Quicksorter();
Quicksorter b = new Quicksorter();

Thread t = new Thread(a);
Thread u = new Thread(b);

int middle = partitionForTheFirstTime(array);

a.setParameters(array, 0, middle - 1);
b.setParameters(array, middle + 1, array.size - 1);

t.start()
u.start();

t.join();
u.join();

Смогут ли два потока увидеть побочные эффекты, вызванные partitionForTheFirstTime()?Другими словами, создает Поток, имеет ли отношение "случается до", или запускает Поток?

Ответы [ 2 ]

8 голосов
/ 07 июня 2011

С раздел 17.4.5 JLS :

Из приведенных выше определений следует:

  • Разблокировка на мониторе происходит перед каждой последующей блокировкой на этом мониторе.
  • Запись в энергозависимое поле (§8.3.1.4) происходит перед каждым последующим чтением этого поля.
  • Вызов функции start () в потоке происходит до любых действий в запущенном потоке.
  • Все действия в потоке происходят до того, как какой-либо другой поток успешно вернется из join () в этом потоке.
  • Инициализация по умолчанию любого объекта происходит перед любыми другими действиями (кроме записи по умолчанию) программы.

Биты о start() и join() являются подходящими для вас - другими словами, когда вы успешно join() создали поток, вы видите все действия в этом потоке. Если вы start() поток, этот новый поток будет видеть все действия, которые уже произошли в потоке, который вызывает start().

РЕДАКТИРОВАТЬ: См. Также "ошибки согласованности памяти" .

0 голосов
/ 07 июня 2011

Если вы не выполните start () перед выполнением partitionForTheFirstTime (), оба потока будут работать с одними и теми же данными. Но вы должны быть осторожны с точки зрения передачи ссылочных значений этим отдельным потокам, в этом примере значение массива передается по ссылке в противоположность примитивным значениям, которые передаются по значению. В результате оба потока будут работать на одной и той же таблице, и это может вызвать условия гонки

...