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

时间:2013-04-08 15:11:21

标签: c# .net 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
    }

2 个答案:

答案 0 :(得分:24)

  

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

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

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

必须从调用EnterWriteLock的同一线程调用

ExitWriteLock。否则,它会抛出SynchronizationLockException。从documentation开始,在以下情况下抛出此异常:

  

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

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

答案 1 :(得分:20)

没有。不应像在您的示例中那样使用线程仿射协调原语。

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

默认情况下,

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

SemaphoreSlim typeasync - 知道(通过其WaitAsync方法),而且Stephen Toub在series of async coordination primitives中也有AsyncEx library