代码之家  ›  专栏  ›  技术社区  ›  DarthVader

字典查找是否需要锁定?

  •  11
  • DarthVader  · 技术社区  · 15 年前
    lock(dictionaryX)
    {
       dictionaryX.TryGetValue(key, out value);
    }
    

    查找字典时是否需要锁定?

    该程序是多线程的,在向dict.dict添加键/值时,dict被锁定。

    9 回复  |  直到 15 年前
        1
  •  2
  •   JaredPar    15 年前

    只有在线程之间同步对资源的访问时才需要锁定。只要不涉及多个螺纹,这里就不需要锁定。

    在从多个线程更新和读取值的上下文中,是的,锁是绝对必要的。实际上,如果您使用的是4.0,那么应该考虑切换到专门为并发访问而设计的集合之一。

        2
  •  11
  •   Kamyar    15 年前

    如上所述 here :

    在不锁定的情况下使用TryGetValue()是不安全的。词典暂时处于不适合阅读的状态,而另一个线程正在编写词典。随着词典所包含的词条数量的增加,词典会不时地重新组织自己。当您在这个重新组织发生的确切时间阅读时,当bucket被更新但尚未更新值条目时,您将面临为键查找错误值的风险。

    更新: 请看“线程安全”部分 this page 也是。

        3
  •  4
  •   Jesse C. Slicer    15 年前

    正如编程中许多微妙的问题一样,答案是:不一定。

    如果只添加值作为初始化,则不需要同步后续读取。但是,另一方面,如果你想一直读写,那么你绝对需要保护这个资源。

    然而,一个全面的 lock 可能不是最好的方法,这取决于你的字典获得的流量。试一试 ReaderWriterLockSlim 如果您使用的是.NET 3.5或更高版本。

        4
  •  3
  •   Jim Mischel    15 年前

    如果有多个线程访问字典,则需要锁定更新和查找。您需要锁定查找的原因是,在执行查找的同时可能发生更新,并且在更新期间字典可能处于不一致的状态。例如,假设有一个线程执行此操作:

    if (myDictionary.TryGetValue(key, out value))
    {
    }
    

    一个单独的线程正在这样做:

    myDictionary.Remove(key);
    

    可能发生的是线程 TryGetValue 确定该项在字典中,但在它可以检索该项之前,其他线程将删除它。结果是执行查找的线程要么抛出异常,要么 TyGET值 会回来 true 但是 value 将是 null 或者可能是一个与键不匹配的对象。

    这是唯一可能发生的事情。如果您在一个线程上进行查找,而另一个线程添加了您试图查找的值,那么也会发生类似的灾难性事件。

        5
  •  2
  •   SnickersAreMyFave    15 年前

    使用 new ConcurrentDictionary<TKey, TValue> object 你可以忘了锁什么的。

        6
  •  1
  •   Yuriy Faktorovich    15 年前

    是的,您需要为在多线程环境中访问而锁定字典。写入字典不是原子的,因此它可以添加键,但不能添加值。在这种情况下,当您访问它时,可能会得到一个异常。

        7
  •  1
  •   Steve Townsend    15 年前

    如果您在.NET 4上,则可以替换为 ConcurrentDictionary 为了安全起见。在 System.Collection.Concurrent namespace .

    如果这是你的选择,不要使用滚你自己的锁。

        8
  •  0
  •   Aamir    15 年前

    是的,如果此字典是多个线程之间的共享资源,则应该锁定。这样可以确保您得到正确的值,而其他线程不会在查找调用期间中途更改值。

        9
  •  0
  •   Nick Martyshchenko    15 年前

    是的,如果字典上有多线程更新,则必须锁定。查看这篇伟大的文章了解详细信息: “Thread safe” Dictionary(TKey,TValue)

    但自从 ConcurrentDictionary<> 介绍您可以通过.NET 4或使用 Rx 在3.5中(它包含System.Threading.dll,实现了新的线程安全集合)