在释放互斥锁后,立即等待,切换​​线程

时间:2017-06-24 18:17:41

标签: c# multithreading mutex semaphore

假设我有一个名为Mutex1

的互斥锁(或信号量)
private static readonly SemaphoreSlim Mutex1 = new SemaphoreSlim(0, 1);

以下代码是否始终符合我的期望?

主题A

await Mutex1.WaitAsync(); // wait in thread "A" until thread "B" releases mutex

主题B

Mutex1.Release();
await Mutex1.WaitAsync(); // thread A should continue and thread B should wait.

线程 B 中的Mutex1.Release始终保证会导致线程 A 继续吗?

我猜的答案是否定的,因为在线程 A 继续之前,线程 B 可能会再次等待,因为"等待线程"没有排队,线程 B 可能会再次继续而不是线程 A 。我是对的吗?

我目前使用的安全方法是使用名为Mutex2的附加字段。

private static readonly SemaphoreSlim Mutex2 = new SemaphoreSlim(0, 1);

主题A

await Mutex1.WaitAsync(); // wait in thread "A" until thread "B" releases mutex

主题B

Mutex1.Release();
await Mutex2.WaitAsync(); // notice Mutex TWO

现在我确定正确处理线程之间的切换,但我想知道是否可以保存一个字段并安全地使用第一种方法。请注意,此操作包含在锁定中,因此其单线程安全。

(对于那些古玩的人来说,这是使用UWP应用程序服务在两个应用程序之间进行同步通信的应用程序的一部分)

2 个答案:

答案 0 :(得分:2)

来自https://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim(v=vs.110).aspx我们有:

  

如果多个线程被阻止,则没有保证的顺序,例如FIFO或LIFO,它控制线程何时进入信号量。

所以,对我来说,这说明苗条的信号量排队请求。

而且,你的第一种方法有竞争条件。也就是说,线程B可以释放互斥锁,立即重新获取它,锁定线程A一段不确定的时间。

因此,您可能必须使用两种信号量方法。或者,使用支持[公平]服务员队列的不同同步原语。

答案 1 :(得分:0)

您使用此方式时,应尝试使用AutoResetEventhttps://msdn.microsoft.com/en-us/library/system.threading.autoresetevent(v=vs.110).aspx

这将做你想要的。