2011-08-10 7 views
2

私は、このコードがスレッドセーフであるかどうか、なぜそうでないのかを知りたいと思います。はこのコードのスレッドセーフですか?

static IMyInterface _myinterface; 
     public static IMyInterface someStuff 
     { 
      get 
      { 
       if (_myinterface== null) 
       { 
        _myinterface= MyServiceLocator.GetCurrent().GetInstance<IMyInterface>(); 
       } 

       return _myinterface; 
      } 
     } 

ありがとうございます!

答えて

1

いいえあなたは、ロックを使用する必要があります。

private static readonly object m_lock = new object(); 
private static IMyInterface _myinterface; 

public static IMyInterface someStuff 
{ 
    get 
    { 
     lock(m_lock) 
     { 
      if (_myinterface == null) 
      { 
      //create instance 
      } 

      return _myinterface; 
     }    
    } 
} 
+2

m_lockも静的でなければなりません... – Dargos

+0

great thx Dargos!それは意味をなさない – Tilupo

+0

私はコードを更新しました...互換性のない応答が他の誰かへの答えとして受け入れられるのは意味がありません。 – Ian

1

私にとってはそうではありません。 ロックを確実に追加する方法があるからです。 if文に2つのスレッドがある可能性があります。

http://msdn.microsoft.com/en-us/library/c5kehkcz%28v=vs.80%29.aspx

+2

2つの「プロセス」?私はスレッド*に気を付けると思いますか? –

+0

気づいてくれてありがとうございました... – ykatchou

1

いいえ、これ以上のことをしたいと思います。 _myinterface==nullのダブルチェックに注目してください。これは、最初のチェックの後で別のスレッドがすでにロックを作成しているためです。だからあなたはあなたのロックに達するとすぐにダブルチェックする必要があります。

static IMyInterface _myinterface; 
private static object lockObj = new object(); 
public static IMyInterface someStuff 
{ 
    get 
    { 
     if (_myinterface== null) 
     { 
     lock(lockObj) 
     { 
      if (_myinterface== null) 
      {    
       _myinterface= MyServiceLocator.GetCurrent().GetInstance<IMyInterface>(); 
      } 
     } 
     } 
     return _myinterface; 
} 
0

いいえ、そうではありません。

なぜですか?

someStuffに2つのコールが入っています。if(_myInterface null)を取得しましたが、中断されました。_myInterface = MYServiceLoc...です。 2番目のスレッドはすべて終了し、スリープ状態に入る前に完了します。第2の目覚めは、_myInterfaceに割り当てます。

MyServiceLocator ...でGetInstance()を呼び出してしまう、両方_myInterfaceに割り当てる、との両方が_myInterfaceに異なる値を返すことができます両方。

1

シングルトンに同時にアクセスしようとする複数の初期化スレッドが存在する可能性があるためではありません。

これは仕事ができる:

static object _lock=new object(); 
    static IMyInterface _myinterface; 
    public static IMyInterface someStuff 
    { 
     get 
     { 
      lock (_lock) { 
       if (_myinterface== null) 
       { 
        _myinterface= MyServiceLocator.GetCurrent().GetInstance<IMyInterface>(); 
       } 
      } 
      return _myinterface; 
     } 
    } 
0

はありません、2つの異なるスレッドが異なるインスタンスをインスタンス化することが起こると_ myInterfaceの前回保存した値をowerwritesことができます。

ちょうどそのスレッド#1はifブロック

if (_myinterface== null)     
{ 
// ... here 

を入力しても_ ​​myinterfaceを読み、今回のスレッド#1インスタンス化されたオブジェクトと_myinterfaceの更新を参照して、あまりにもこのブロックに入る#2スレッド想像してみてください。 同時に、スレッド#2はすでに_myinterfaceの値をキャッシュしています(NULLです)。スレッド#1に格納されている新しい1つのオブジェクトとowerwriting値を作成しています。

ロックによってラップゲッター()ので、一つだけのスレッドが他の人のよう(ダブルロックに関する他の回答を参照してください)で

4

を入力することができ、それはない、と述べています。ただし、プレーンロックやダブルチェックパターンからスレッドセーフなappletを作成するためのオプションがありますが、CLRのすべての(可能な)実装で動作することは保証されていません。

はまた、あなたが高い競合が予想される場合を除き、二重にチェックロックが本当に必要とされていないとほとんど違いをしないことに注意してください。間違ってしまうのは比較的簡単です(最初の誤った実装を参考にしてください)。

詳細については、Jon Skeet's articleを参照してください。

+0

非常に良い記事です。 –

+0

+1ダブルチェックロックに問題があることを指摘してください。先日のこれの古典的な例を修正しました。 –

+0

これを行う安全な方法のコード例は、あなたの答えに追加されます。 :) –

関連する問題