【问题标题】:When to use lock statements in concurrency何时使用并发锁语句
【发布时间】:2012-08-30 20:21:45
【问题描述】:

我无法理解在我的代码中使用 lock() 语句的方式。我有几个像这样的静态集合:

private static Dictionary<string, User>() Users = new Dictionary<string, User>();

我不断地添加、删除、更新和阅读这个集合。我意识到当我添加、删除或更新时,我应该锁定Users,但是当我从集合中读取时,我必须锁定它吗?执行诸如搜索键并在字典中返回User 之类的正确方法是什么?我在考虑创建一个新的 Dictionary 实例,然后将用户复制到该实例,然后从中读取,或者我可以直接从中读取吗?

【问题讨论】:

    标签: c# asp.net concurrency


    【解决方案1】:

    这里最好的选择可能是移除锁,并使用ConcurrentDictionary&lt;string, User&gt; 而不是Dictionary&lt;string, User&gt;

    否则,您还需要同步读取。您可以从多个线程中读取,但如果在读者阅读时作家将写入字典,则需要同步。 ReaderWriterLock(或ReaderWriterLockSlim)在这种情况下工作得很好,因为它们可以允许多个读取器,但只允许一个写入器。一个简单的lock 也可以,但会比需要的更频繁地阻塞。

    【讨论】:

    • 对于像添加/删除/读取字典这样简单的操作而言,ReaderWriterLoc(Slim) 的锁定时间不是过大吗?
    • @DirkBonné 这完全取决于 - 它通常是最合适的机制(尽管在 .NET 4 中,我只使用 ConcurrentDictionary)。如果你有很多读取器,但偶尔有重叠的写入器,这将比锁执行得更好,因为锁会阻塞并发读取。
    【解决方案2】:

    但是当我从集合中读取时,我必须锁定它吗?

    是的,如果另一个线程可能会在读取期间修改字典。

    在字典中搜索键并返回用户的正确方法是什么?

    使用TryGetValue 方法。

    如果您使用的是 .Net 4.0 或更高版本,则可以使用线程安全的 ConcurrentDictionary 集合。

    【讨论】:

    • 如果您只是阅读,则无需锁定。如果您正在阅读,而其他人可能会或可能不会同时在写作,那么您需要锁定。
    • @Servy - 感谢您指出这一点,我应该更具体一些;答案已更新。
    【解决方案3】:

    如果您使用C# 4.0 或更多,您可以使用ConcurentDictionary 来处理所有这些内容。

    如果你没有或者因为某种原因不能使用4.0,是的,你需要在ReadWriteContains上自己实现锁定机制,模拟基本的ACID原理,比如

    • 一致
    • 隔离
    • 耐用性。

    不要认为 原子性 在这种情况下有什么意义。

    希望这会有所帮助。

    【讨论】:

    • 这只确保每个单独的操作看起来都是原子的。如果您曾经执行多个相互依赖的方法,您需要lock
    • @Servy: 给我时间写点东西:)
    • 原子性可以;从外部观察到,在ConcurrentDictionary 上调用的所有方法都是原子的(对于那些采用Func 的方法并不严格,但如果它们是功能性的Func - 并且它们有这个名字是有原因的 - 那么它们可能被调用不会被观察到不止一次)。
    【解决方案4】:

    你可以使用 ConcurrentDictionary

    LIink : http://msdn.microsoft.com/en-us/library/dd287191.aspx

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-26
      • 2019-01-28
      • 1970-01-01
      相关资源
      最近更新 更多