lock vs AcquireReader&作家锁

时间:2009-11-01 09:57:26

标签: c# multithreading locking

我发现我的应用程序可能会减速,所以我有两个问题:

  1. 简单锁定对象和读取器/写入器锁之间的真正区别是什么? 例如。我有一组客户,很快就会改变。对于迭代,我应该使用readerlock还是简单的锁就足够了?
  2. 为了减少负载,我已经离开了一个集合的迭代(只读取)而没有任何锁定。此集合经常快速更改,但使用writerlocks添加和删除项目。它是否安全(我不介意偶尔跳过的项目,这个方法在循环中运行并且它并不重要)让这个读取不受锁定的保护?我只是不想随机例外。

2 个答案:

答案 0 :(得分:2)

不,您当前的情况是安全。

特别是,如果一个集合在迭代时发生变化,那么你将在迭代线程中获得InvalidOperationException。您应该在迭代器的整个持续时间内获得读取器锁:

  • 获取读者锁
  • 迭代收集
  • 释放读卡器锁

请注意,与为迭代的每个步骤获取读取器锁定相同 - 这将无济于事。

至于读取器/写入器锁和“普通”锁之间的区别 - 读取器/写入器锁的想法是多个线程可以同时读取,但只有一个线程可以写入(并且只有在没有一个时)在看书)。在某些情况下,这可以提高性能 - 但它也会增加解决方案的复杂性(在正确的方面)。如果可能的话,我还建议您使用.NET 3.5中的ReaderWriterLockSlim - 它比原始ReaderWriterLock更有效,并且ReaderWriterLock IIRC存在一些固有问题。 / p>

我个人通常使用简单的锁,直到我证明锁竞争是性能瓶颈。您是否已经分析了您的应用程序,以找出瓶颈所在?

答案 1 :(得分:2)

首先关于没有锁定事物的阅读迭代。这不安全,你不应该这样做。只是以最简单的方式说明这一点 - 您正在迭代一个集合,但您永远不知道该集合中有多少项目并且无法找到。你在哪里停下来?每次迭代检查计数都没有用,因为它可以在您检查之后但在获得元素之前发生变化。

ReaderWriterLock是为允许多个线程具有并发读访问权但强制同步写入的情况而设计的。从您的应用程序的声音中,您没有多个并发读取器,并且写入与读取一样普遍,因此ReaderWriterLock没有任何好处。在这种情况下,您可以通过经典锁定获得更好的服务。

一般来说,无论是通过多线程锁定对共享对象的访问权限而挤出的微小性能优势都会被随机怪异和无法解释的行为所大大抵消。锁定共享的所有内容,测试应用程序,然后当一切正常时,您可以在其上运行探查器,检查应用程序等待锁定的时间,然后在需要时实施一些危险的技巧。但是,影响可能会很小。

“我们应该忘记小的效率,大约97%的时间说:过早的优化是所有邪恶的根源。然而,我们不应该在那个关键的3%中放弃我们的机会。一个优秀的程序员不会因为这样的推理而自满,他会明智地仔细研究关键代码;但只有在识别出代码之后才会“ - Donald Knuth