等待信号灯的正确方法是什么

本文关键字:方法 是什么 信号灯 等待 | 更新日期: 2023-09-27 17:56:08

我认为下面的代码会让所有 10 个线程运行,一次运行两个,然后在调用 10 次后打印"done"Release()。但事实并非如此:

        int count = 0;
        Semaphore s = new Semaphore(2, 2);
        for (int x = 0; x < 10; x++)
        {
            Thread t = new Thread(new ThreadStart(delegate()
            {
                s.WaitOne();
                Thread.Sleep(1000);
                Interlocked.Increment(ref count);                       
                s.Release();
            }));
            t.Start(x);
        }
        WaitHandle.WaitAll(new WaitHandle[] { s });
        Console.WriteLine("done: {0}", count);

输出:

done: 6

如果实现我正在寻找的功能的唯一方法是将EventWaitHandle传递给每个线程,然后在这些EventWaitHandles数组上执行WaitAll(),那么在仅包含信号量的数组上进行WaitAll()是什么意思?换句话说,等待线程何时解锁?

等待信号灯的正确方法是什么

WaitHandle.WaitAll只是等到所有处理程序都处于信号状态。

因此,当您在一台WaitHandle上调用WaitHandle.WaitAll时,它的工作方式与您调用s.WaitOne()相同

例如,您可以使用以下代码等待所有已启动的线程,但允许两个线程并行运行:

int count = 0;
Semaphore s = new Semaphore(2, 2);
AutoResetEvent[] waitHandles = new AutoResetEvent[10];
for (int x = 0; x < 10; x++)
    waitHandles[x] = new AutoResetEvent(false);
for (int x = 0; x < 10; x++)
{
    Thread t = new Thread(threadNumber =>
        {
            s.WaitOne();
            Thread.Sleep(1000);
            Interlocked.Increment(ref count);
            waitHandles[(int)threadNumber].Set();
            s.Release();
        });
    t.Start(x);
}
WaitHandle.WaitAll(waitHandles);
Console.WriteLine("done: {0}", count);
WaitHandle.WaitAll(new WaitHandle[] { s });就像

s.WaitOne();一样等待。它一有机会就进入。您似乎希望此调用等待所有其他信号量操作,但操作系统无法区分。此命令很可能是第一个被授予对信号量的访问权限的命令。

我认为你需要的是Barrier类。它是为分叉连接式并行性而设计的。