C#字典的多线程访问

3

我了解到,在向 C# 字典中添加、读取和删除元素时,它们并不支持多线程安全;但是,如果另一个线程正在写入、读取和从字典中删除元素,是否可以以线程安全的方式访问 C# 字典的 Count 属性呢?


2
您是否期望它返回正确的值? - Brian Rasmussen
或者直接使用ConcurrentDictionary... http://msdn.microsoft.com/zh-cn/library/dd287191.aspx - David Peden
6个回答

2

由于属性在底层是一个方法调用,所以实际情况并不像乍一看那么简单。

  • T1: 访问 Count 属性
  • T1: 调用 get_Count() 方法(某种 JMP/GOTO ASM 指令)
  • T1: 读取代表项目数量的变量 == 1
  • T2: 添加新项目,实际数量变为 2
  • T1: 返回 1,但实际上已经有两个项目了

因此,如果应用程序逻辑依赖于 Count 属性值,则理论上可能会出现竞态条件


因为属性不能直接写入,因此并发读取属性并不完全安全。后者并不遵循前者,这是一种危险的想法。 - usr
我正在撰写我的答案,起初我的想法是错误的,你是正确的。 - sll

2
它应该是线程安全的,因为它不会崩溃,但我相当确定它不是线程安全的,因为其他线程操作字典可能导致您无法获得正确的计数。【编辑:正如usr所指出的那样,仅仅因为在这个级别上目前是线程安全的并不意味着它将继续保持线程安全。您没有任何保证】

1
首先:这是危险的想法。如果您将这样的东西投入生产中,请非常小心。可能,您应该只使用锁或ConcurrentDictionary。
您对近似答案感到满意吗?
但是:反射器显示count只读取某些字段并返回它。这很可能永远不会改变。因此,在这种情况下,您可以合理地冒这个风险。

0
你可以将字典创建为静态只读对象,并在修改时使用lock来处理大部分问题,我想这应该可以解决。

0
根据您想要实现的目标,您可以使用ReaderWriterLockSlim来保护字典。这样,您就可以更快地进行读取,并且只在执行变异操作时锁定字典。

0

与其假设,我去反编译器里看了一下:

public int Count
{
    get
    {
        // count and freeCount are local fields
        return (this.count - this.freeCount);
    }
}

是的,它是“线程安全”的,因为访问它不会导致字典对象损坏。话虽如此,如果另一个线程正在访问字典,我不确定是否可以想到任何使用情况,其中准确获取计数很重要。


你认为我只是在不看完整个答案的情况下写评论吗?“如果字典被另一个线程访问,我可以想到任何需要准确计数的用例。”正确,但这种想法很有限。 - L.B

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接