在异步方法中使用ReaderWriterLockSlim是否安全

use*_*198 23 .net c# multithreading

由于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
    }
Run Code Online (Sandbox Code Playgroud)

Ree*_*sey 25

在异步方法中使用ReaderWriterLockSlim是否安全

是的,不是.在异步方法中使用它是安全的,但在异步方法中使用它可能不安全,在异步方法中进入和退出跨越的锁await.

在这种情况下,不,这不一定是安全的.

必须从调用的同一线程调用ExitWriteLockEnterWriteLock.否则,它抛出一个SynchronizationLockException.从文档中,在以下情况下抛出此异常:

当前线程未在写入模式下进入锁定状态.

唯一一次这是安全的,如果这是在异步方法中使用的,该异步方法总是存在一个环境,其中有一个当前的SynchronizationContext东西将把东西移回同一个线程(即:Windows窗体,WPF等),以及嵌套异步调用不使用嵌套异步调用,其中调用链上的"父"设置任务ConfigureAwait(false)(这将阻止Task捕获同步上下文).如果您处于该特定场景中,您将知道该线程将被维护,因为该await调用会将您封送回调用上下文.


Ste*_*ary 21

不应该在您的示例中使用线程仿射协调原语.

您正确地确定了可以使用不同的线程在之后恢复的问题await.由于async方法提前返回的方式还有另一个问题:调用者不知道锁是否被保留.

ReaderWriterLockSlim默认情况下是非递归锁,因此如果另一个async方法尝试使用相同的锁,则会出现死锁.即使你使锁递归,你仍然会遇到一个问题:在持有锁时永远不应该调用任意最终用户代码,而这基本上就是你在使用时所做的事情await.

SemaphoreSlim类型async知晓的(通过它的WaitAsync方法)和斯蒂芬Toub有一系列的async协调原语,我也可以AsyncEx库.

  • @DonBox:只需单击一个按钮即可获得作者锁定,然后执行`await Task.Delay(10000);`并在 10 秒过去之前再次单击它。 (2认同)