C#线程和放大器;闭塞 [英] C# Threading & Blocking

查看:113
本文介绍了C#线程和放大器;闭塞的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道哪一个是更好的方法在一个线程安全的方式加载数据。传统上,我已经使用了双锁模式和服务的目的相当不错。现在,增加System.Lazy型的,我想知道如果依靠懒惰和加载的内部更好,在一个更​​好的方法做的工作。它看起来更清洁和更容易阅读,但岂不是更好?



有什么想法?

 命名空间SomeNameSpace 
{
公共类DataStoreContext
{
私人只读静态懒惰< D​​ataStoreContext>上下文=新懒人< D​​ataStoreContext>(()=>新建DataStoreContext());
私人懒<&字典LT;字符串,实体GT;> _entities =新懒人<&字典LT;字符串,实体GT;>(()=> {返回DataStoreContext.Instance.Load();});
私人只读对象_syncRoot =新的对象();
私人DataStoreContext()
{
}

公众解释<字符串,实体GT;数据
{
{返回_entities.Value; }
}

公共静态DataStoreContext实例
{
{返回context.Value; }
}

私人字典<字符串,实体GT;负荷()
{一些数据存储
//加载数据。
返回NULL;
}

私人字典<字符串,实体GT; LoadWithLock()
{
如果(_entities == NULL)
{
锁(_syncRoot)
{
如果(_entities == NULL)
{
&字典LT;字符串,实体GT;实体= this.Load();
_entities =实体;
返回_entities;
}
}
}

返回_entities;
}

公共无效清除()
{

_entities =新懒人<字典<字符串,实体GT;>(()=> {返回DataStoreContext.Instance.Load();});

}
}
}


解决方案

它看起来更清洁和更容易阅读,但岂不是更好?




是。双检锁是很难得到的权利。它需要一个内存屏障是正确的。你的实现是不实际的CIL保证安全*。



有关详细信息,请参阅的这个维基百科条目



通过使用懒< T> ,你得到的代码不仅是清洁,但实际上是在所有平台上正确的。



*请注意,这可能完美的作品在x86和x64 ,运行Microsoft运行时,由于该平台的存储器模型。但是,它不是由规范的保证是没有适当的内存屏障正确的。


I am wondering which one is better approach to load data in a thread safe fashion. Traditionally, I have used the double lock pattern and that served the purpose quite well. Now, with the addition of System.Lazy type, I am wondering if relying on the internals of Lazy and Loading is better and do the job in a much better way. It does look cleaner and easier to read but is it better?

Any thoughts?

namespace SomeNameSpace
{
  public class DataStoreContext
  {
    private readonly static Lazy<DataStoreContext> context = new Lazy<DataStoreContext>(() => new DataStoreContext());
    private Lazy<Dictionary<string, Entity>> _entities = new Lazy<Dictionary<string, Entity>>(() => { return DataStoreContext.Instance.Load(); });
    private readonly object _syncRoot = new object();
    private DataStoreContext()
    {
    }

    public Dictionary<string, Entity> Data
    {
      get { return _entities.Value; }
    }

    public static DataStoreContext Instance
    {
      get { return context.Value; }
    }

    private Dictionary<string, Entity> Load()
    {
      // Load Data from some data store. 
      return null;
    }

    private Dictionary<string, Entity> LoadWithLock()
    {
      if (_entities == null)
      {
        lock (_syncRoot)
        {
          if (_entities == null)
          {
            Dictionary<string, Entity> entities = this.Load();
            _entities = entities;
            return _entities;
          }
        }
      }

      return _entities ;
    }

    public void Clear()
    {

     _entities = new Lazy<Dictionary<string, Entity>>(() => { return DataStoreContext.Instance.Load(); });

    }
  }
}

解决方案

It does look cleaner and easier to read but is it better?

Yes. Double-checked locking is difficult to get right. It requires a memory barrier to be correct. Your implementation isn't actually guaranteed safe by the CIL*.

For details, see this Wikipedia entry.

By using Lazy<T>, you get code that is not only cleaner, but is actually correct on all platforms.

*Note that this likely works perfectly on x86 and x64, running the Microsoft runtime, due to the memory model of the platform. However, it's not guaranteed by spec to be correct without proper memory barriers.

这篇关于C#线程和放大器;闭塞的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆