理解限制:C# 中的 await
和 lock
C# 的 await
关键字对于异步编程至关重要,可实现非阻塞操作。 但是,严格禁止在 await
语句内使用 lock
。此限制是防止常见错误源(死锁)的关键设计选择。
Microsoft 的文档解释说 await
中的 lock
表达式会产生风险。 代码的执行可以在 await
产生控制权后暂停,稍后在可能不同的线程上恢复。这种时间间隙可能会导致其他线程获取锁、反转锁顺序并导致死锁的情况。
让我们看一个假设的例子:
<code class="language-csharp">class Async { public static async Task<IDisposable> Lock(object obj) { while (!Monitor.TryEnter(obj)) await Task.Yield(); return new ExitDisposable(obj); } private class ExitDisposable : IDisposable { private readonly object obj; public ExitDisposable(object obj) { this.obj = obj; } public void Dispose() { Monitor.Exit(this.obj); } } }</code>
此代码尝试模仿异步锁定,但正如编译器所示,它很容易在 ExitDisposable.Dispose()
内无限期阻塞,从而可能导致死锁。 发生这种情况是因为 Monitor.Exit
可能在与获取锁的线程不同的线程上执行,从而可能违反锁定顺序。
本质上,在await
内禁止lock
是一种主动措施,以避免多线程应用程序中出现死锁。 最好避免将异步操作与 lock
语句相结合,并考虑替代同步方法,例如读写锁或来自 System.Threading
.
以上是为什么 C# 中的'lock”语句中禁止使用'await”?的详细内容。更多信息请关注PHP中文网其他相关文章!