例如,如果我有以下代码:
if (dictionary == null) {
dictionary = new ConcurrentDictionary();
}
Run Code Online (Sandbox Code Playgroud)
多个线程可以读取它是否为null并同时创建新的ConcurrentDictionaries?
我在谈论System.Collections.Concurrent提供的ConcurrentDictionary
https://msdn.microsoft.com/en-us/library/dd287191(v=vs.110).aspx
ConcurrentDictionary是线程安全的.但是你展示的代码与内部代码无关ConcurrentDictionary.一切都ConcurrentDictionary在你的责任范围内.所以你应该确保只进行一次初始化.
一种方法是使用Lazy(T).
Lazy<ConcurrentDictionary> _dictionary = new Lazy<ConcurrentDictionary>(() => new ConcurrentDictionary());
Run Code Online (Sandbox Code Playgroud)
只需调用Value即可获取字典实例.Lazy只会初始化一次字典,并且还会处理初始化部分的线程安全性.
var dic = _dictionary.Value; // extract instance.
Run Code Online (Sandbox Code Playgroud)
大多数构造函数都是线程安全的,因为它们只发生在一个线程上。如果它们访问静态字段或调用非\xe2\x80\x93线程安全委托或其他东西,则存在例外,但它们很少见(通常是一个坏主意)。
\n\n但这不是您问题的关键,因为在您的示例中,可能竞争的不是构造函数,而是作业。
\n\n如果另一个线程可以访问dictionary,那么确实存在竞争,并且一个线程可以分配给dictionary另一个线程以被另一个线程覆盖(并且可能有一个时期,两个线程认为dictionary具有不同的值)。
这可能是个问题。它可能只是次优的(例如,并发字典被用作缓存,一些缓存的值丢失并且必须重新计算,但事情仍然有效)或者它可能是灾难性的。如果dictionary对多个线程可见,那么您应该锁定并重新测试,使用Interlocked.CompareExchange或Lazy<ConcurrentDictionary>。
| 归档时间: |
|
| 查看次数: |
304 次 |
| 最近记录: |