提问人:creativergk 提问时间:11/12/2023 最后编辑:creativergk 更新时间:11/12/2023 访问量:67
处理 async/await 时的锁定行为 [closed]
Locking behaviour when dealing with async/await [closed]
问:
我可能想多了,但我不确定在处理 await/async 时我是否理解锁定是如何工作的。
鉴于以下情况,在每次之后,不同的线程可以返回执行下一段代码,对吧?(除非在具有类似 WPF 的线程上运行)await
TaskScheduler
await Task.Run(async () =>
{
// ThreadPoolWorker 1
await Something();
// ThreadPoolWorker 2
await SomethingElse();
// ThreadPoolWorker 3
await SomethingElse2();
// ThreadPoolWorker 4
});
因此,考虑到这一点,我最终会遇到以下问题,我使用 .第一个任务进入 on ,锁也进入,但从另一个线程返回,例如 。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();
...
});
我猜处理它的方式是必须始终在调用它的线程上返回?这是在 SemaphoreSlim 本身实现的吗?await Semaphore.WaitAsync
答:
0赞
DasKrümelmonster
11/12/2023
#1
使用具有输出和未满足的特定期望的完整代码示例,您的问题会更好。
但是,我会尝试以我理解的方式回答它。因此,对于此代码:
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();
});
你担心的是 2 个任务同时运行,线程 1 执行第一个任务的前半部分,因此具有信号量并可以绕过第二个任务等待?
那不会发生。请记住,任务是应按顺序执行的命令,可以由不同的线程执行,每个线程在每次等待后由另一个线程接管。但是,这也意味着等待实际上并未在任何线程上完成。可以这样想:
- 线程 1 开始任务 A 的进度,并遇到等待。信号量块和任务被搁置,因为它此时无法进一步执行。
- 同时,线程 5 开始了任务 B 的进度,并将其搁置一旁,因为它在接下来的 5 秒内无法执行
- 线程池空闲
- 主线程调用 Semaphore.Release()
- 因此,任务 A 变为可执行任务,线程(线程 2)抓取它并进一步运行它。
- 计时器过后,任务 B 再次符合条件。线程 1 抓住它并继续。调用 WaitAsync() 时,需要再次搁置 Task。这是因为信号量知道它的状态并且很忙。
- 有人调用 Release()
- 任务 B 再次符合条件,并且某些线程可以拾取它
或者换个说法,哪个线程启动 WaitAsync() 或哪个线程之后接管并不重要。重要的是,(完整的)信号量的发布将导致一个任务变得可执行,即使许多人正在等待它。
评论
0赞
creativergk
11/13/2023
谢谢。我困惑的根源还在于,我认为 SemaphoreSlim 具有线程亲和力,而实际上并非如此。所以 semaphoreSlim 不会有我想到的问题,......但是互斥锁会,因为它确实具有线程亲和力
评论
semaphoreSlim.Release()
Release
semaphoreSlim
initialCount