8

スレッドセーフな方法でデータをロードするには、どちらがより良いアプローチなのか疑問に思っています。伝統的に、私はダブルロックパターンを使用してきましたが、それは目的に非常に役立ちました. さて、System.Lazy 型が追加されたことで、Lazy と Loading の内部構造に依存する方が良いかどうか、そしてより良い方法で仕事をするかどうか疑問に思っています。きれいで読みやすいように見えますが、それよりも優れていますか?

何かご意見は?

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(); });

    }
  }
}
4

2 に答える 2

8

きれいで読みやすいように見えますが、それよりも優れていますか?

はい。二重チェックのロックを正しく行うのは困難です。正しいメモリバリアが必要です。あなたの実装は、実際には CIL* によって安全であるとは保証されていません。

詳細については、このウィキペディアのエントリを参照してください。

を使用するLazy<T>と、よりクリーンなだけでなく、すべてのプラットフォームで実際に正しいコードが得られます。

*これは、プラットフォームのメモリ モデルにより、Microsoft ランタイムを実行している x86 および x64 で完全に機能する可能性が高いことに注意してください。ただし、仕様では、適切なメモリ バリアなしで正しいことは保証されていません。

于 2012-10-10T01:08:42.373 に答える
3

MSDN のドキュメントによると:

デフォルトでは、Lazy クラスのすべての public および protected メンバーはスレッド セーフであり、複数のスレッドから同時に使用できます。これらのスレッドセーフ保証は、型のコンストラクターへのパラメーターを使用して、オプションでインスタンスごとに削除できます。

読み取り操作と書き込み操作の両方でスレッドセーフです。したがって、これははるかにクリーンなので、これに固執すると思います。

ただし、ドキュメントに記載されているように、コンストラクターへのいくつかのオプションのパラメーターを使用して、そのスレッド セーフを無効にすることができます。

于 2012-10-10T01:07:49.707 に答える