You could simplify things a bit.
- You could use one
CountdownEvent
instead of waiting for 3 handles to be signaled. cde.Wait
will block until it has been signaled 3 times.
- You could also use a
SemaphoreSlim
to release multiple threads, instead of using 3 different handles. sem.Release(3)
will unblock up to 3 threads blocked on sem.Wait()
.
static CountdownEvent cde = new CountdownEvent(3);
static SemaphoreSlim sem = new SemaphoreSlim(3);
static void X()
{
new Thread(Waiter).Start();
new Thread(Waiter).Start();
new Thread(Waiter).Start();
for (; ; )
{
cde.Wait();
Debug.WriteLine("new round");
cde.Reset(3);
sem.Release(3);
}
}
static void Waiter()
{
for (; ; )
{
sem.Wait();
Thread.Sleep(1000);
Debug.WriteLine("Waiter run");
cde.Signal();
}
}
Note that now all threads can reuse the same code.
Edit:
As stated in the comments, one thread might steal another thread's round.
If you don't want this to happen, a Barrier
will do the job:
private static Barrier _barrier;
private static void SynchronizeThreeThreads()
{
_barrier = new Barrier(3, b =>
Debug.WriteLine("new round"));
new Thread(Waiter).Start();
new Thread(Waiter).Start();
new Thread(Waiter).Start();
//let the threads run for 5s
Thread.Sleep(5000);
}
static void Waiter()
{
while(true)
{
Debug.WriteLine("Thread {0} done.", Thread.CurrentThread.ManagedThreadId);
_barrier.SignalAndWait();
}
}
You add 3 participants to the barrier. The first and second participants to reach the barrier (i.e., to execute _barrier.SignalAndWait()
) will block until the remaining participants reaches it too. When all participants have reached the barrier, they will all be released and go for another round.
Notice that I passed a lambda to the barrier constructor - that's the "post-phase action", an action that will be executed after all participants have reached the barrier, and before releasing them.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…