想象一下存储Foo集合的ConcurrentDictionary。是否有必要担心Foo的Bar属性的线程安全性(例如,线程1获取Bar的值,同时线程2设置值)?或者字典本身的并发性是否使属性线程安全?
//Bar with no lock
public class Foo
{
public string Bar { get; set; }
}
//Bar with lock
public class Foo
{
private readonly object barLocker = new object();
private string bar;
public string Bar
{
get
{
lock(barLocker)
{
return bar;
}
}
set
{
lock(barLocker)
{
bar = value;
}
}
}
}
答案 0 :(得分:1)
ConcurrentDictionary
的方法是线程安全的,但不会扩展到字典中项目的方法或属性。
这是一个单元测试来演示。它执行以下操作:
如果ConcurrentDictionary
使其中的对象成为线程安全的,那么新的字符串属性应至少与原始属性的长度相同。
结果呢?测试偶尔会通过,但通常会失败。字符串属性的长度因测试而异,因为更新的属性不是线程安全的。
[TestClass]
public class ConcurrentDictionaryTests
{
[TestMethod]
public void DoesntMakeContentsThreadsafe()
{
var s = "1010101010101010101010101010101010101010";
var dictionary = new ConcurrentDictionary<int, ClassWithProperty>();
dictionary.TryAdd(1, new ClassWithProperty());
Parallel.ForEach(s, c => dictionary[1].TheString += c);
Assert.AreEqual(s.Length, dictionary[1].TheString.Length);
}
}
public class ClassWithProperty
{
public string TheString { get; set; }
}
另一种观察方式 - 如果将对象放在ConcurrentDictionary
中使其属性为线程安全,那么对于大量多线程属性来说,这将是一个简单的解决方法。需要一个对象是线程安全的吗?只需将其放入ConcurrentDictionary
。