Releasing mutex 后立即等待,切换​​线程

Wait immediately after Releasing mutex, switching threads

假设我有一个名为 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 可能会再次等待,因为 "waiting threads" 是未排队,线程 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 应用程序服务在两个应用程序之间进行同步通信的应用程序的一部分)

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

If multiple threads are blocked, there is no guaranteed order, such as FIFO or LIFO, that controls when threads enter the semaphore.

所以,对我来说,这表明 slim 信号量不会排队请求。

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

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

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

这将如你所愿。