在异步方法中使用ReaderWriterLockSlim是否安全
由于ReaderWriterLockSlim
类使用线程ID来查看谁拥有锁,因此可以安全地使用异步方法,其中没有保证所有方法都将在同一线程上执行。
例如。
System.Threading.ReaderWriterLockSlim readerwriterlock = new System.Threading.ReaderWriterLockSlim(); private async Task Test() { readerwriterlock.EnterWriteLock(); await Task.Yield(); //do work that could yield the task readerwriterlock.ExitWriteLock(); //potentailly exit the lock on a different thread }
在异步方法中使用ReaderWriterLockSlim是否安全
是的,不是。 在异步方法中使用它是安全的,但在异步方法中使用它可能不安全,在异步方法中进入和退出跨越await
的锁。
在这种情况下,不,这不一定是安全的。
必须从调用EnterWriteLock
的同一线程调用EnterWriteLock
。 否则,它会抛出SynchronizationLockException
。 从文档中 ,在以下情况下抛出此exception:
当前线程未在写入模式下进入锁定状态。
唯一一次这是安全的,如果这是在异步方法中使用的,该异步方法总是在一个环境中,当前有一个当前的SynchronizationContext
将把东西移回同一个线程(即:Windows Forms,WPF等),并且嵌套异步调用没有使用它,其中调用链上的“父”使用ConfigureAwait(false)
设置任务ConfigureAwait(false)
(这将阻止Task
捕获同步上下文)。 如果您处于该特定场景中,您将知道线程将被维护,因为await
调用将封送您回到调用上下文。
不应该在您的示例中使用线程仿射协调原语。
您正确地确定了在await
之后可以使用不同线程恢复的问题。 由于async
方法提前返回的方式还有另一个问题:调用者不知道锁被保持。
默认情况下, ReaderWriterLockSlim
是非递归锁,因此如果另一个async
方法尝试使用相同的锁,则会出现死锁。 即使你使锁递归,你仍然会遇到一个问题:在持有锁时永远不应该调用任意的最终用户代码,这基本上就是你在使用await
时所做的事情。
SemaphoreSlim
类型是async
WaitAsync
(通过其WaitAsync
方法),而Stephen Toub有一系列async
协调原语也可以在我的AsyncEx库中使用 。