我可以在get访问器中锁定一个集合吗?

时间:2011-06-20 14:01:02

标签: c# .net multithreading

我有一个很少使用的字典,几乎不会被阅读或更新,因为单个项目引发事件并返回其事件args的结果。事实上,线程总是会使用相同的线程进行更新。我正在考虑添加一个简单的锁只是为了安全。我想知道我是否可以将锁放在get访问器中。这有用吗?

        Dictionary<string,Indicator> indicators = new Dictionary<string,Indicator>();
        Dictionary<string, Indicator> Indicators
        {
            get
            {
                lock (indicators)
                {
                    return indicators;
                }
            }
        }

        public void AddIndicator(Indicator i)
        {
            lock (indicators)
            {
                indicators.Add(i.Name, i);
            }
        }

4 个答案:

答案 0 :(得分:6)

这没有做任何特别有用的事,没有。

特别是,如果你有:

x = foo.Indicators["blah"]

然后索引器将被执行而没有持有锁的线程...所以它不是线程安全的。想想上面这样的代码:

Dictionary<string, Indicator> indicators = foo.Indicators;
// By now, your property getter has completed, and the lock has been released...
x = indicators["blah"];

除了通过索引器访问它之外,您是否需要对集合执行任何操作?如果没有,您可能只想用一个方法替换该属性:

public Indicator GetIndicator(string name)
{
    lock (indicators)
    {
        return indicators[name];
    }
}

(您可能希望使用TryGetValue等等 - 这取决于您要实现的目标。)

我个人更喜欢使用对私有和否则未使用的锁对象的引用,而不是锁定集合引用,但这是一个单独的事情。

正如其他地方所述,ConcurrentDictionary是您的朋友如果您正在使用.NET 4,但当然在此之前它不可用:(

答案 1 :(得分:4)

除了Jon的输入之外,我会说不要从MSDN开始锁定集合indicators

  

锁定实例时要小心,   例如在C#中锁定(this)   Visual Basic中的SyncLock(Me)。如果是其他   应用程序中的代码,外部   类型,锁定对象,   可能会出现死锁。

建议使用专用的object实例锁定。还有其他地方可以了解更多细节和原因 - 即使在这里,你是否应该在有空的时候搜索信息。

答案 2 :(得分:3)

或者,您可以使用ConcurrentDictionary来处理线程安全问题。

答案 3 :(得分:0)

简答:是的。
为什么不应该这样做,但正如Jon所说,它在使用索引时没有按预期锁定?