锁定Dictionary.Count

时间:2012-12-07 21:18:47

标签: c# locking

在访问集合的简单属性时,锁定是否有任何好处或危害,特别是.Count? (这是可取的,不可取的,或者丝毫没关系?)(当然我需要将其锁定在任何写入或读取上)

private Dictionary<string, bool> database = new Dictionary<string, bool>();
private object databaseLock = new object();
public int Count
{
    get
    {
        lock (databaseLock)
        {
            return database.Count;
        }
    }
}

就我个人而言,我认为这可能是明智之举,只是为了敲定约会需要锁定对字典的访问,而不是出于任何实际原因[*]。此外,在您访问的任何属性中,可能会有超过一个操作的操作。

[*]知道在C#中的(大多数)集合中Count是一个由它维护的整数,所以应该始终是一个原子操作

3 个答案:

答案 0 :(得分:4)

是的,在并发写入的情况下需要锁定,因为Dictionary的文档不能保证这是安全的。你不能假设它的内部结构。

此规则的例外情况需要极端情况。

TL; DR:仅依靠记录在案的行为,否则你最终会陷入一个受伤的世界。

答案 1 :(得分:2)

这种代码大部分属于“伤害”类别。非常严重的伤害。锁只是不保护任何东西。在属性getter退出锁定后的一纳秒内,没有任何东西阻止线程在字典中添加或删除项目。这使得Count值只返回垃圾。获得值时,您不知道字典中有多少项。到目前为止,这个错误最有害的方面是通常正确。

此代码将保证您创建了一个线程竞赛,这是迄今为止最严重的诊断错误。

答案 2 :(得分:1)

编辑:正如我们在answer Dictonary.Count中指出的那样,它不是线程安全的。 documentation说:

  

枚举集合本质上不是线程安全的   程序。在极少数情况下,枚举与写入竞争   访问时,必须在整个枚举期间锁定集合。

这意味着需要同步 。请注意,可能正在修改集合的任何其他代码都需要使用相同的锁。这非常容易出错,如果多个线程使用Dictionary,请考虑使用ConcurrentDictionary而不是