C#线程和阻塞

我想知道哪一个更好的方法以线程安全的方式加载数据。 传统上,我使用了双锁模式,这很好地达到了目的。 现在,通过添加System.Lazy类型,我想知道是否依赖于Lazy和Loading的内部更好并以更好的方式完成工作。 它看起来更干净,更容易阅读,但它更好吗?

有什么想法吗?

namespace SomeNameSpace { public class DataStoreContext { private readonly static Lazy context = new Lazy(() => new DataStoreContext()); private Lazy<Dictionary> _entities = new Lazy<Dictionary>(() => { return DataStoreContext.Instance.Load(); }); private readonly object _syncRoot = new object(); private DataStoreContext() { } public Dictionary Data { get { return _entities.Value; } } public static DataStoreContext Instance { get { return context.Value; } } private Dictionary Load() { // Load Data from some data store. return null; } private Dictionary LoadWithLock() { if (_entities == null) { lock (_syncRoot) { if (_entities == null) { Dictionary entities = this.Load(); _entities = entities; return _entities; } } } return _entities ; } public void Clear() { _entities = new Lazy<Dictionary>(() => { return DataStoreContext.Instance.Load(); }); } } } 

它看起来更干净,更容易阅读,但它更好吗?

是。 双重检查锁定很难正确。 它需要内存屏障才能正确。 CIL *实际上并未保证您的实施安全。

有关详细信息,请参阅此Wikipedia条目 。

通过使用Lazy ,您获得的代码不仅更清晰,而且在所有平台上实际上都是正确的。

*请注意,由于平台的内存模型,这可能在运行Microsoft运行时的x86和x64上完美运行。 但是,如果没有适当的内存屏障,则不能保证规格是正确的。

根据MSDN的文档:

默认情况下,Lazy类的所有公共成员和受保护成员都是线程安全的,并且可以从多个线程同时使用。 可以使用类型构造函数的参数,可选地和每个实例删除这些线程安全保证。

对于读取和写入操作来说,它非常安全。 因此,我会说坚持这一点,因为它更清洁。

但是,正如文档所述,您可以使用构造函数的一些可选参数关闭该线程安全性。