问题标签 [readerwriterlockslim]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c# - Parallel.ForEach 中的死锁与 ReaderWriterLockSlim
我的应用程序中有一个有趣的死锁问题。有一个内存数据存储,它使用 ReaderWriterLockSlim 来同步读取和写入。其中一个读取方法使用 Parallel.ForEach 来搜索给定一组过滤器的商店。其中一个过滤器可能需要对同一存储进行恒定时间读取。这是产生死锁的场景:
更新:下面的示例代码。使用实际方法调用更新的步骤给定的
单例实例store
ConcreteStoreThatExtendsGenericStore
- Thread1在存储上获得读锁 -
store.Search(someCriteria)
- Thread2尝试使用写锁更新存储 -
store.Update()
- 阻塞Thread1 - Thread1对存储执行 Parallel.ForEach 以运行一组过滤器
- Thread3(由Thread1的 Parallel.ForEach 产生)尝试对存储进行恒定时间读取。它试图获得读锁,但被Thread2的写锁阻塞。
- Thread1无法完成,因为它无法加入Thread3。 Thread2无法完成,因为它被Thread1阻塞。
理想情况下,如果当前线程的祖先线程已经拥有相同的锁,我想做的不是尝试获取读锁。有没有办法做到这一点?还是有另一种/更好的方法?
c# - 这个 ReaderWriterLockSlim 锁定模式看起来正确吗?
我一直在使用ReaderWriterLockSlim来同步读/写,到目前为止效果很好。
我有一组对象,读/写锁保存在Dictionary<string, ReaderWriterLockSlim>
. 我有一个需要以原子方式获取多个读锁的场景。我确定我没有任何代码允许一个线程同时尝试持有多个写锁,这让我认为下面的代码可以毫无问题地工作。
如果我尝试使用写锁而不是读锁的方法,我几乎可以肯定我最终会遇到死锁,除非我可以确保锁定总是以相同的顺序发生(在我的情况下我不能)。
假设以下情况,是否有人看到此代码有任何问题:
- 在其他地方,不允许持有写锁的线程持有任何其他锁(读或写)
- 多个线程可以同时持有任意数量的读锁
有什么想法吗?
c# - 可以更新或删除的共享内存的线程安全枚举
我在线程之间有一个共享对象,用于保存文件状态信息。保存信息的对象是这个类:
}
我这样称呼这本字典: SynchronizedDictionary _cache = new SynchronizedDictionary();
可以生成其他线程并像这样使用线程:_cache["key"];
字典可以在运行时修改。我认为这里没有问题。还是我错了?在我看来,问题在于枚举器,因为我想创建一个遍历集合的枚举器。我该怎么做呢?我想到了这三个解决方案:
- 像这样制作枚举器:http: //www.codeproject.com/Articles/56575/Thread-safe-enumeration-in-C (但使用 ReaderWriterLockSlim)
- 公开锁对象,就像 SyncRoot 一样(但使用 ReaderWriterLockSlim),因此调用者调用进入和退出读取方法。
- 改用数据库(SQLite fx)来保存信息。
数字 1) 的问题是:
- 它使用构造函数进入读取模式。如果手动调用 GetEnumerator() 而不使用 foreach 会怎样?忘记调用 dispose。
- 我不知道这是否是一种好的编码风格。尽管我喜欢代码。
- 如果调用者使用 foreach,我不知道调用者在枚举器的实例化和调用 dispose 之间可能会做什么。如果我理解了我正确阅读的文档,只要剩下一个读者做一些繁重的工作,这最终可能会阻止作者。
2)的问题是:
- 我不喜欢暴露这个。我知道 .NET API 可以做到这一点,但不喜欢它。
- 由调用者正确进入和退出
3)我的眼睛没有问题。但是我做这个小项目是作为一个业余项目,我想了解更多关于多线程和反射的知识,所以我想把它作为最后的选择。我想在运行时迭代集合的原因是我想找到符合某些条件的值。
也许只有我发明了一个问题?
我知道 ConcurrentDictionary,但我不想使用它。我将这个项目用作游乐场。玩线程和反射。
编辑
我被问到我在阅读和写作什么。我将在本次编辑中讲述这一点。我正在阅读和写作这门课:
我正在做很多读取,并且在运行时几乎没有写入。也许我会写 2000 和 1 篇。也不会有很多对象,也许是 200 个。
c# - C# ReaderWriterLockSlim 避免递归的最佳实践
我有一个使用ReaderWriterLockSlim的类,该类具有读取方法和使用读取方法检索要修改的元素的写入方法。一个简单的例子是:
如上所述,此代码LockRecursionException
在调用时抛出一个,因为在尝试进入读锁ChangeFoo()
时已经持有写锁。GetFoo()
我已经检查了文档ReaderWriterLockSlim
,我可以使用它LockRecursionPolicy.SupportsRecursion
来允许上述工作。但是,文档还建议不要将其用于任何新开发,而应仅在升级现有代码时使用。
鉴于此,在写入方法可以使用只读方法检索需要修改的内容的情况下,实现相同结果的最佳实践是什么?
c# - ReaderWriterLockSlim 出错
我得到了这个异常
读取锁正在被释放而不被持有。
在 System.Threading.ReaderWriterLockSlim.ExitReadLock() 在 .. GetBreed(String)
下面是代码中唯一可以访问锁的地方。如您所见,没有递归。我无法理解这个异常是如何发生的。
multithreading - 更快的 TMultiReadExclusiveWriteSynchronizer?
有没有更快的那种TMultiReadExclusiveWriteSynchronizer
?也许是 FastCode?
从 Windows Vista 开始,Microsoft 添加了Slim Reader/Writer lock。它的性能比 Delphi 的TMultiReadExclusiveWriteSynchronizer
. 不幸的是,它只存在于 Windows Vista 及更高版本中,实际上很少有客户拥有。
大概 a 中使用的概念Slim Reader/Writer lock
可以在本机 Delphi 代码中重做 - 但有人做过吗?
我有一种情况,在 a 上获取和释放锁TMultiReadExclusiveWriteSynchronizer
(即使没有争用 - 单个线程)会导致 100% 的开销(操作时间加倍)。我可以在没有锁定的情况下运行,但是我的类不再是线程安全的。
有更快的TMultiReadExclusiveWriteSynchronizer
吗?
注意:如果我使用 aTCriticalSection
我只会遭受 2% 的性能损失(尽管已知关键部分在获取成功时会很快,即当它是单线程并且没有争用时)。CS 的缺点是我失去了“多个阅读器”的能力。
测量结果
使用TMultiReadExclusiveWriteSynchronizer
相当多的时间花在里面BeginRead
and EndRead
:
然后,我将代码移植到使用 Window 自己的SlimReaderWriter 锁(一些代码重写,因为它不支持递归锁获取),并分析了结果:
TMultiReadExclusiveWriteSynchronizer
: 10,698 ns 每次迭代
10,697,772,613 ns 迭代 1,000,000 次SRWLock
: 8,802 ns 每次迭代
8,801,678,339 ns 迭代 1,000,000 次Omni Reader-Writer lock
: 8,941 ns 每次迭代
8,940,552,487 ns 迭代 1,000,000 次
使用 SRWLocks(又名 Omni 的旋转锁)时提高了 17%。
现在,我无法永久切换代码以使用Windows Vista SRWLocks,因为有一些完整的客户企业仍在使用 Windows XP。
Slim 锁只是对InterlockedCompareExchange
功能的谨慎使用;但比我能成功使用的要小心。我离窃取所涉及的 140 条机器指令还差得很远,并且已经完成了。
奖金阅读
c# - 如何知道谁拥有 ReaderWriterLockSlim?
我正在编写一个广泛使用多线程的应用程序。一些线程使用 ReaderWriterLockSlim 共享一个 observablecollection。
我不时遇到死锁,我需要知道在死锁时哪个线程持有锁。我怎么知道这个?我查看了对象属性,没有明显的东西。目前我只知道哪些线程正在等待锁。
谢谢你的帮助!
编辑:当然,我说的是在调试时找到它,并提供所有可用的调试信息。
c# - 在 IDisposable 处理程序中包装 ReaderWriterLockSlim
全部,
对我来说,使用 IDisposable 模式来控制 ReaderWriterLockSlim 锁似乎很自然,因为它允许在没有额外的 try/catch 块的情况下清理锁。我注意到 BCL 中没有任何东西可以处理这个常见的(ish)任务,所以我想知道我下面的代码是否真的很幼稚?我在 SO 上看到了一些与这个一般领域相关的其他问题,但没有什么能正面解决这个想法的适当性。
问题也不在于是否应该调用 ReaderWriterLockSlim 对象上的 Dispose() 方法,而只是包装器。
用法:
c# - ReaderWriterLockSlim vs 双锁检查模式
编辑:从我已经得到的答案中,我了解到我提出的第一个解决方案,并不是真正的“不阻塞读取”,因为只有一个线程可以进入可升级锁并且在读取释放之前不能获取写入锁......
所以我的问题是,如果不存在,如何以正确的方式使第一个解决方案成为“非阻塞读取”的创建?
我试图了解非阻塞多线程读取的两种解决方案。以下两种解决方案有什么区别(也许我仍然不明白一些事情,但我正在尝试):
在我看来,这两种解决方案都可以进行非阻塞读取,并且仅在写入时阻塞……如果是这样,有什么好处ReaderWriterLockSlim
?正如我在 google 中发现的那样,Monitor
它比ReaderWriterLockSlim
. 当然,我知道我在阅读时可能会得到不正确的字典状态,但这对我来说没关系。
谢谢
c# - 是否存在有利于读者的 ReaderWriterLockSlim 等价物?
我使用ReaderWriterLockSlim已经有一段时间了,到目前为止它已经满足了我的需求。当我继续微调我的应用程序时,我发现这ReaderWriterLockSlim
对于我的用例来说不是最理想的。
根据文档(和我的经验),它有利于作者而不是读者(即当读者和作者排队时,作者将获得优先权)。但是,我需要一个有利于读者的等价物。我了解此类组件的副作用(特别是作家饥饿问题)。
是否有任何人可以指出的生产就绪等价物?谢谢。