在异步方法中使用ReaderWriterLockSlim安全吗?
本文关键字:安全 ReaderWriterLockSlim 异步方法 | 更新日期: 2023-09-27 18:08:08
由于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
的锁。
在这种情况下,不,这并不一定安全。
ExitWriteLock必须从调用EnterWriteLock
的同一个线程中调用。否则,抛出一个SynchronizationLockException
。从文档中可以看出,当:
当前线程未进入写模式。
唯一安全的时候是,如果这是在一个异步方法中使用的,这个方法总是在一个环境中,那里有一个当前的SynchronizationContext
,它将把东西移回同一个线程(即:Windows窗体,WPF等),并且不是由一个嵌套的异步调用使用,其中一个"父"在调用链上设置了一个任务与ConfigureAwait(false)
(这将防止Task
捕获同步上下文)。如果您在那个特定的场景中,您将知道该线程将被维护,因为await
调用将把您送回调用上下文。
No。线程仿射协调原语不应像您的示例中那样使用。
您正确地识别了在await
之后可以使用不同线程来恢复的问题。由于async
方法提前返回的方式,还有另一个问题:调用者不知道锁被持有。
ReaderWriterLockSlim
默认情况下是一个非递归锁,所以如果另一个async
方法试图获取同一个锁,就会出现死锁。即使你让锁递归,你仍然会遇到一个问题:在持有锁的时候,不应该调用任意的终端用户代码,而这实际上就是你使用await
时所做的事情。
SemaphoreSlim
类型是async
-aware(通过它的WaitAsync
方法),Stephen Toub有一系列的async
协调原语也可以在我的AsyncEx库。