假设我有:
MyCollection = new ConcurrentDictionary<string, int>();
我现在可以安全地从MyCollection
中添加和删除项目。但是修改项目呢。例如,这样做安全吗:
MyCollection["key"] = 1; // thread 1
和
MyCollection["key"] = 2; // thread 2
示例2:
MyCollection2 = new ConcurrentDictionary<string, List<int>>();
这样做安全吗?
MyCollection2["key"].Add(1); // Thread1
和
MyCollection2["key"].Add(2); // Thread2
其中Thread1和Thread2同时执行。修改项目时是否必须创建锁?
修改项是否安全完全取决于它是否在ConcurrentDictionary
中。这与你从两个不同的线程中变异出一个列表没有什么不同。在List
的情况下,它是不安全的;如果使用设计为的类型从多个不同的线程进行突变,例如ConcurrentDictionary<string, ConcurrentQueue<int>>
,那么这就可以了。
ConcurrentQueue
仅确保对该类的方法的调用被观察为原子调用;它在螺纹安全方面没有做出任何其他保证。
第一个是完全安全的。ConcurrentDictionary是线程安全的,因此同时在不同线程上获取/设置值不会引起问题。
你的第二个不安全。仅仅因为ConcurrentDictionary包含对X类型实例的引用并不能使X类型成为线程安全的。在访问任何特定键的值时,它也不会阻塞。
记住,
MyCollection2["key"].Add(1);
与相同
var list = MyCollection2["key"];
list.Add(1);
很明显,在这种情况下,所有线程安全的代码(ConcurrentDictionary访问)都已完成,但非线程安全代码(List<T>
访问)具有而不是。