我可能想得太多了,但我不确定我是否理解在处理等待/异步时锁定是如何工作的。
考虑到以下情况,在每个
await
之后,不同的线程可以返回执行下一段代码,对吗? (除非在带有 TaskScheduler
的线程上运行,例如 WPF)
await Task.Run(async () =>
{
// ThreadPoolWorker 1
await Something();
// ThreadPoolWorker 2
await SomethingElse();
// ThreadPoolWorker 3
await SomethingElse2();
// ThreadPoolWorker 4
});
考虑到这一点,我最终会不会遇到以下问题,我使用
Task.Run()
启动了两项任务。第一个任务进入 WaitAsync()
上的 Thread1
,因此 Thread1
拥有锁,但从另一个线程上的 WaitAsync
返回,例如 Thread 2
。
同时,在第二个
Task.Run()
中,Thread 5
进入了Task.Delay()
,但是当它从await
返回时,理论上可能会在Thread 1
上吗? ..所以现在不用等待锁了?
Task.Run(async () =>
{
// Thread 1
await semaphoreSlim.WaitAsync();
// Thread 2
...
});
Task.Run(async () =>
{
// Thread 5
await Task.Delay(5000);
// Thread 1
await semaphoreSlim.WaitAsync();
...
});
我猜测处理此问题的方式是
await Semaphore.WaitAsync
必须始终在调用它的线程上返回?这是在 SemaphoreSlim 本身中实现的吗?
如果有完整的代码示例,您的问题会更好,该代码示例具有输出和未满足的特定期望。
不过,我会尝试按照我的理解来回答。所以对于这段代码:
Task.Run(async () => // Task A
{
// Thread 1
await semaphoreSlim.WaitAsync();
// Thread 2
});
Task.Run(async () => // Task B
{
// Thread 5
await Task.Delay(5000);
// Thread 1
await semaphoreSlim.WaitAsync();
});
您担心的是,两个任务同时运行,线程 1 执行第一个任务的前半部分,因此拥有信号量,可以绕过第二个等待?
这不会发生。请记住,任务是应按顺序执行的命令,并且可以由不同的线程执行,每次等待后由另一个线程接管。但是,这也意味着等待实际上并未在任何线程上完成。这样想吧:
换句话来说,哪个线程启动 WaitAsync() 或哪个线程随后接管并不重要。重要的是,(完整的)信号量的释放将导致只有一个任务变得可执行,即使许多任务正在等待它。