Size: a a a

2020 July 04

O

Oleg in pro.jvm
0 1 2
источник

AS

Aleksey Shipilev in pro.jvm
かたかわ
Надо подождать, пока два треда отработают
Вот, а как это подождать?
источник

かたかわ in pro.jvm
notify
источник

かたかわ in pro.jvm
и wait механизм
источник

O

Oleg in pro.jvm
かたかわ
Надо подождать, пока два треда отработают
треды дальше себе работают, по условию задачи :)
источник

AS

Aleksey Shipilev in pro.jvm
Thread 1: a[0] = 1;
Thread 2: a[1] = 1;
Thread 3: thread1.join(); thread2.join(); print(a[0] + a[1]); // гарантированно печатает "2"
источник

かたかわ in pro.jvm
Aleksey Shipilev
Thread 1: a[0] = 1;
Thread 2: a[1] = 1;
Thread 3: thread1.join(); thread2.join(); print(a[0] + a[1]); // гарантированно печатает "2"
Угу
источник

かたかわ in pro.jvm
Да
источник

かたかわ in pro.jvm
Но это не синхронизация 🌚
источник

AS

Aleksey Shipilev in pro.jvm
С точки зрения JMM -- Thread.join есть synchronized action, связывающее с последним действием в потоке, так што...
источник

かたかわ in pro.jvm
Мне кажется, Олег немного не это имел в виду, пардон, если я его не так понял
источник

O

Oleg in pro.jvm
かたかわ
Мне кажется, Олег немного не это имел в виду, пардон, если я его не так понял
это и имел
источник

かたかわ in pro.jvm
Oleg
это и имел
Окей
источник

AS

Aleksey Shipilev in pro.jvm
Дальше, из соображений про цепочки release-acquire:
Thread 1: a[0] = 1; future1.set(true);
Thread 2: a[1] = 1; future2.set(true);
Thread 3: future1.get(); future2.get(); print(a[0] + a[1]); // гарантированно печатает "2"

Так, в принципе, с передачей данных туда-сюда работают практически все пулы потоков.
источник

AS

Aleksey Shipilev in pro.jvm
По абсолютно тем же причинам (release-acquire) работает
volatile boolean thread1Done, thread2Done;
Thread 1: a[0] = 1;  thread1Done = true;
Thread 2: a[1] = 1;  thread2Done = true;
Thread 3: while(!thread1Done); while(!thread2Done); print(a[0] + a[1]); // гарантированно печатает "2"
источник

AS

Aleksey Shipilev in pro.jvm
Равно как работает без волатайлов, но с локами:
boolean thread1Done, thread2Done;
final Object lock = new Object();
Thread 1: a[0] = 1; synchronized(lock) { thread1Done = true; lock.notifyAll(); }
Thread 2: a[1] = 1; synchronized(lock) { thread2Done = true; lock.notifyAll(); }
Thread 3: synchronized(lock) { while (!thread1Done || !thread2Done) lock.wait(); }; print(a[0] + a[1]); // гарантированно печатает "2"
источник

O

Oleg in pro.jvm
Aleksey Shipilev
Равно как работает без волатайлов, но с локами:
boolean thread1Done, thread2Done;
final Object lock = new Object();
Thread 1: a[0] = 1; synchronized(lock) { thread1Done = true; lock.notifyAll(); }
Thread 2: a[1] = 1; synchronized(lock) { thread2Done = true; lock.notifyAll(); }
Thread 3: synchronized(lock) { while (!thread1Done || !thread2Done) lock.wait(); }; print(a[0] + a[1]); // гарантированно печатает "2"
только в первом будет параллельная работа
источник

AS

Aleksey Shipilev in pro.jvm
Oleg
только в первом будет параллельная работа
в каком смысле? в примере с локами лок берётся только для выставления флагов и нотификации ;)
источник

O

Oleg in pro.jvm
Aleksey Shipilev
в каком смысле? в примере с локами лок берётся только для выставления флагов и нотификации ;)
а, точно, не заметил
источник

AS

Aleksey Shipilev in pro.jvm
общий паттерн видите?
Thread 1: a[0] = 1; <RELEASE 1>
Thread 2: a[1] = 1; <RELEASE 2>
Thread 3: <ACQUIRE 1> <ACQUIRE 2> print(a[0] + a[1]); // гарантированно печатает "2"

Вся дичь с локами не обязана вылезать за рамки release/acquire ;)
источник