PulseAll в C#
Метод PulseAll будит все потоки, которые ждут на этом мониторе. Его вызывают, когда новое состояние важно для всех ожидающих сразу.
После пробуждения каждый снова берёт блокировку и только потом продолжает работу.
Два потока ждут на одном мониторе, затем их будят одним сигналом. Пауза перед сигналом даёт им успеть дойти до ожидания, иначе сигнал пропадёт и потоки зависнут. Оба увеличивают счётчик по очереди, потому что блокировку держит только один:
object gate = new();
int done = 0;
Thread a = new(() => { lock (gate) { Monitor.Wait(gate); Interlocked.Increment(ref done); } });
Thread b = new(() => { lock (gate) { Monitor.Wait(gate); Interlocked.Increment(ref done); } });
a.Start(); b.Start();
Thread.Sleep(10);
lock (gate) Monitor.PulseAll(gate);
a.Join(); b.Join();
Console.WriteLine(done); // выведет 2
Запустите три потока. В каждом дождитесь сигнала и прибавьте 1 к общему полю. Разбудите все три одним сигналом, дождитесь их и выведите поле.