c# - 信号量如何从另一个线程中释放?

标签 c# multithreading semaphore

据我所知,线程可以释放信号量,而无需先使用 WaitOne 获取锁。

因此,如果我们有线程 A、B 和 C 以及一个信号量,则 A 和 B 调用 WaitOne,获得锁定并开始执行其任务。
随之而来的是线程 C,它只对信号量调用 Release

这应该使信号量的计数增加 1。这是否意味着信号量将终止 A 或 B,或者只允许第三个线程获取锁并在其池中拥有 3 个线程,即使最大值为 2?

最佳答案

考虑

var semaphore = new SemaphoreSlim(2);

这意味着此时信号量只有 2 个执行槽,但您必须记住,这只是执行槽的初始数量(用于同时授予的请求) )。

因此,如果我们将 A、B、C 线程生成到具有 2 个执行槽的信号量中,则前两个线程将被执行,而 C 线程将排队,直到代码中的其他人向该信号量发出信号为止。再添加一个执行槽。

当有人说可以执行队列中的下一个线程时,无论其他线程如何,C都会被执行。


一些技术示例:

(正如我在@dmitri-nesteruk 的类(class)中​​看到的)

可用执行槽总数由 CurrentCount 表示。

每次线程想要执行时,它都会询问信号量是否有可用的执行槽(CurrentCount > 0),如果为 true - 则可以随意执行,如果没有进入内部队列。

信号量如此令人困惑的原因是 CurrentCount 值可以减少或增加。

  • 每次调用 Wait() 时,它都会减少 1 线程,这意味着少了一个可用的执行槽 并且正在执行一个线程。

  • 每次 Release(1) 被执行时,它都会增加一(或更多) 在代码的其他地方调用,这意味着还有一个 所以第一个线程在信号量里面有可用的执行槽 队列正在执行(它不会终止其他队列)。

在此示例中,我们生成 3 个线程,但只有前两个线程会被执行,直到有人对信号量说他可以通过使用 Release 增加 CurrentCount 来释放另一个执行槽(1).

for (int i = 0; i < 3 ; i++)
{
    Task.Factory.StartNew(() => 
    {
        Console.WriteLine($"Spawning task: {Task.CurrentId}");
        semaphore.Wait(); //CurrentCount--
        Console.WriteLine($"Executing task: {Task.CurrentId}");
    });
}


while (semaphore.CurrentCount <= 2)
{
    Console.ReadKey();
    Console.WriteLine("Key pressed");
    semaphore.Release(1); //CurrentCount++
}

输出:

Spawning task: A
Spawning task: B
Spawning task: C
Executing task: A
Executing task: B
.....
Key pressed
Executing task: C

关于c# - 信号量如何从另一个线程中释放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54401113/

相关文章:

c# - 异步套接字读取 : the initiating thread must not be exited - what to do?

linux - 在 Linux 中控制信号量队列中的出队顺序

c++ - 多生产者-消费者执行的效率

c# - 跨 UWP 应用和 Azure 移动服务的持久身份验证

c# - VS 2010 - 输出窗口 - 如何启用 "find message in code"按钮?

c# - 盒装值类型比较

python - multiprocessing.Semaphore 和 multiprocessing.BoundedSemaphore 有什么区别?

c# - asp.net MVC 模型绑定(bind)一个字节数组

java - java线程间通信

java - 我可以在JAVA中的catch中启动一个线程吗