Don*_*Box 0 c# asynchronous locking
在他的回答中,/sf/answers/1376510621/
斯蒂芬·克利里提到
ReaderWriterLockSlim 是一种线程仿射锁类型,因此通常 不能与 async 和 await 一起使用。
他所说的“通常”是什么意思?什么时候可以ReaderWriterLockSlim使用?
另外,我在这里读http://joeduffyblog.com/2007/02/07/introducing-the-new-readerwriterlockslim-in-orcas/是ReaderWriterLockSlim有不同的怪癖,但这篇文章是从2007年开始它是否从那时起改变?
我猜您发布了一个只有 Cleary 才能回答的问题,因为您想知道他的意思。
同时,从他的声明中可以明显看出ReaderWriterLockSlim,在任何情况下,您都可以使用with async/await来保证获取锁的同一线程也能够释放它。
例如,你可以想象这样的代码:
private readonly ReaderWriterLockSlim _rwls = new ReaderWriterLockSlim();
async void button1_Click(object sender, EventArgs e)
{
_rwls.EnterWriteLock();
await ...;
_rwls.ExitWriteLock();
}
Run Code Online (Sandbox Code Playgroud)
在上面,因为Click事件将在await将返回到的线程中引发,您可以获取锁,执行await,并且仍然可以在延续中释放锁,因为您知道它将是同一个线程。
在async/ 的许多其他用途中await,不能保证继续在该方法产生的线程中,因此不允许释放在await. 在某些情况下,这显然是故意的(即ConfigureAwait(false)),在其他情况下,这只是await. 无论哪种方式,这些场景都与示例ReaderWriterLockSlim的方式不兼容Click。
(我故意忽略了一个更大的问题,即获取一个锁然后在可能长时间运行的异步操作期间保持它是否是个好主意。也就是说,正如他们所说, “一个完整的‘另一个球o’蜡” 。)
附录:
关于我忽略的“更大的问题”的“简短”评论,太长而不能成为实际评论……
在“更大的问题”是相当广泛和高度依赖于上下文的。这就是为什么我没有解决它。简短版本分为两部分:
一般来说,锁应该保持很短的时间,但一般来说异步操作的持续时间可能很长,所以两者是互不同意的。在进行并发操作时,锁是一种必要的邪恶,但它们总是在某种程度上否定并发操作的好处,因为它们具有序列化其他并发操作的效果。
持有锁的时间越长,一个或多个线程被阻塞等待某事的可能性就越大,序列化他们所做的任何工作。它们都在等待同一个锁,所以即使长时间运行的锁被释放,它们仍然必须按顺序工作,而不是并发。这有点像交通堵塞,一长队汽车在等待施工卡车完成堵塞道路......即使卡车离开,也需要一些时间来清除堵塞。
我不会说是天生的在异步操作期间持有锁是不好的——也就是说,我可以想象经过深思熟虑的场景是可以的——但它经常会破坏其他实现目标,并且在某些情况下可以完全撤消本应大量使用的设计并发,尤其是在没有非常小心的情况下完成时。
从语义上讲,很容易犯错误,即await您知道锁定会在持续时间内保持不变,但“即发即忘”并不少见,并且会导致代码在异步操作发生时看起来锁定,但实际上它不是(参见 Stack Overflow 问题在 Invoke/BeginInvoke 期间锁会发生什么?(事件调度)作为一个例子,某人确实这样做了,甚至没有意识到这一点)。避免错误代码的一种方法是简单地避免已知可能导致错误的编码模式。
同样,如果足够小心,就可以避免这个错误。但通常最好简单地更改实现以使用不太复杂的方法,并养成这样做的习惯。
| 归档时间: |
|
| 查看次数: |
792 次 |
| 最近记录: |