2012-10-10 19 views
8

スレッドセーフな方法でデータをロードする方が良い方法は何ですか?伝統的に、私はダブルロックパターンを使用しており、それは目的を十分に果たしました。さて、System.Lazyタイプを追加して、LazyとLoadingの内部構造に頼っている方がより良い方法で作業を進めているかどうか疑問に思っています。それはより清潔で見やすくなりますが、より良いですか?C#スレッディングとブロッキング

どのような考えですか? MSDNのドキュメント毎の

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

    } 
    } 
} 

答えて

3

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

読み取りと書き込みの両方の操作でスレッドセーフです。したがって、私はそれがはるかにきれいなので、これに固執すると言うでしょう。

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

+0

Clear()の呼び出し時にエンティティを正しく読み込まなかったため、バグが導入されていることがわかりました。私はそれを見るほど、私はそれが好きです。私はSystem.Lazyをもっと活用するつもりです。 入力いただきありがとうございます。 – Sam

+0

@Sam、私は助けになることができてうれしいです。 –

8

見た目が清潔で読みやすくなりますが、それは良いですか?

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

詳細については、this Wikipedia entryを参照してください。

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

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

+0

ありがとう! – Sam

関連する問題