ReaderWriterLockSlim问题 [英] ReaderWriterLockSlim questions

查看:80
本文介绍了ReaderWriterLockSlim问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在他的回答中, https://stackoverflow.com/a/19664437/4919475

斯蒂芬·克莱里(Stephen Cleary)提到

Stephen Cleary mentioned

ReaderWriterLockSlim是线程仿射锁类型,因此通常 不能与async和await一起使用.

ReaderWriterLockSlim is a thread-affine lock type, so it usually cannot be used with async and await.

通常"是什么意思?什么时候可以使用ReaderWriterLockSlim?

What did he mean by "usually"? When can ReaderWriterLockSlim be used?

此外,我在这里已阅读 http ://joeduffyblog.com/2007/02/07/introducing-the-new-readerwriterlockslim-in-orcas/ReaderWriterLockSlim有不同的怪癖,但本文来自2007年.此后是否有所改变?

Also, I've read here http://joeduffyblog.com/2007/02/07/introducing-the-new-readerwriterlockslim-in-orcas/ that ReaderWriterLockSlim has different quirks, but this article is from 2007. Did it change since then?

推荐答案

我想您已经发布了一个只有Cleary可以回答的问题,因为您想知道的意思.

I guess you've posted a question that only Cleary can answer, because you want to know what he means.

同时,从他的陈述中得出的明显推论是,在任何情况下,只要能够保证获得锁的同一线程也可以使用ReaderWriterLockSlimasync/await,您就可以避免使用它.能够释放它.

In the meantime, the obvious inference from his statement is that you can get away with using ReaderWriterLockSlim with async/await in any situation where you are able to guarantee the same thread that acquired the lock will also be able to release it.

例如,您可以想象这样的代码:

For example, you could imagine code like this:

private readonly ReaderWriterLockSlim _rwls = new ReaderWriterLockSlim();

async void button1_Click(object sender, EventArgs e)
{
    _rwls.EnterWriteLock();
    await ...;
    _rwls.ExitWriteLock();
}

在上面,由于Click事件将在await返回到的线程中引发,因此您可以获取锁,执行await,并且仍然可以继续释放锁,因为您知道它将是同一线程.

In the above, because the Click event will be raised in a thread where await will return to, you can acquire the lock, execute the await, and still get away with releasing the lock in the continuation, because you know it'll be the same thread.

async/await的许多其他用法中,不能保证继续在产生该方法的线程中进行,因此不允许释放在此方法之前获取它的锁. await.在某些情况下,这显然是故意的(即ConfigureAwait(false)),在其他情况下,这只是await上下文的自然结果.无论哪种方式,这些方案都与Click示例所兼容的方式与ReaderWriterLockSlim不兼容.

In many other uses of async/await, the continuation is not guaranteed to be in the thread in which the method yielded, and so it wouldn't be allowed to release the lock having acquired it previous to the await. In some cases, this is explicitly intentional (i.e. ConfigureAwait(false)), in other cases it's just a natural outcome of the context of the await. Either way, those scenarios aren't compatible with ReaderWriterLockSlim the way the Click example would be.

(我故意忽略了一个更大的问题,即获取锁然后在可能长时间运行的异步操作期间保持锁是一个好主意.也就是说,正如他们所说,整个'nother ball o'wax"(完整的'nother ball o'wax).)

(I am intentionally ignoring the larger question of whether it's a good idea to acquire a lock and then hold it for the duration of a potentially long-running asynchronous operation. That is, as they say, "a whole 'nother ball o' wax" .)

附录:

关于"<更大>问题"的简短"评论,太长了,无法成为实际评论,我忽略了…

A "short" comment, which is too long to be an actual comment, regarding the "larger question" I am ignoring…

更大的问题" 范围很广,高度依赖于上下文.这就是为什么我没有解决这个问题.简短版本分为两部分:

The "larger question" is fairly broad and highly context-dependent. It's why I didn't address it. The short version is in two parts:

  1. 通常,锁应该保留很短的时间,但是通常来说,异步操作的持续时间可能很长,因此两者是互不相容的.进行并发操作时,锁是必不可少的罪恶,但锁在某种程度上总是会抵消并发操作的好处,因为它们具有序列化否则并发操作的效果.

    您持有锁的时间越长锁定后,一个或多个线程被阻塞等待某事,序列化他们所从事的任何工作的可能性就越大.它们都在等待同一个锁,因此即使释放了长期运行的锁,它们也都必须按顺序工作,而不是同时工作.这有点像交通拥堵,一排排的汽车正在等待工程卡车完成对道路和螺旋路的阻塞;即使卡车不碍事,清除它也要花费一些时间.

    我不会说在异步操作过程中固有地 不好锁—也就是说,我可以想像出经过深思熟虑的场景,在这种情况下可以实现—但它常常会破坏其他实现目标,并且在某些情况下可能会完全撤消旨在大量并发的设计,尤其是在不加小心的情况下进行的设计.

  1. In general, locks should be held for brief periods of time, but in general asynchronous operations are known to be potentially long in duration, so the two are mutually disagreeable. Locks are a necessary evil when doing concurrent operations, but they will always to some extent negate the benefit of doing things concurrently, because they have the effect of serializing otherwise-concurrent operations.

    The longer you hold a lock, the greater the likelihood of one or more threads getting blocked waiting for something, serializing whatever work they have. They are all waiting on the same lock, so even once the long-running lock is released, they still will all have to work in order, not concurrently. It's a bit like a traffic jam where a long queue of cars is waiting for a construction truck to finish blocking the road…even once the truck is out of the way, it will take some significant time to clear the jam.

    I would not say is inherently bad to hold a lock during an asynchronous operation — that is, I can imagine carefully thought-out scenarios where it would be okay — but it very often will undermine other implementation goals, and can in some cases completely undo a design meant to be heavily concurrent, especially when done without great care.

从理论上讲,很容易犯一个错误,即使用await您知道锁定在整个持续时间内都保持不变,但是发射后忘记"并不少见,并且会导致代码在同时锁定发生了异步操作,但实际上却没有(请参见堆栈溢出问题在Invoke/BeginInvoke期间锁发生了什么?(事件调度) 举例说明了确实做到了这一点,甚至没有意识到的人).避免错误代码的一种方法是简单地避免已知可能导致错误的编码模式.

同样,如果足够小心,就可以避免错误.但是通常最好只是简单地更改实现,以使用不太棘手的方法,并养成这样做的习惯.

Semantically it's easy to make a mistake, i.e. with await you know the lock remains for the duration, but "fire-and-forget" is not uncommon, and would lead to the code appearing to lock while an asynchronous operation is occurring, but in reality it not (see the Stack Overflow question What happens to a lock during an Invoke/BeginInvoke? (event dispatching) for an example of someone who did exactly this, and didn't even realize it). One methodology for avoiding buggy code is to simply avoid patterns of coding known to potentially lead to bugs.

Again, if one is careful enough, one can avoid the bug. But it is generally better to simply change the implementation to use a less tricky approach, and to be in the habit of doing so.

这篇关于ReaderWriterLockSlim问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆