2017-02-18 8 views
0

ある作業の完了後にコールバックと呼ばれる次のメソッドがあるとします。メソッドスコープのローカル変数に対して操作を保護する必要がありますか

public class MyClass 
    { 
     private static object _synblock = new object(); 

    public void MyCallBackMethod() 
    { 
     Dictionary<int, int> myDict = new Dictionary<int, int>(); 

     lock(_synblock) 
     { 
      myDict.Add(1, 1); 
     } 

    } 
} 

このメソッドは、複数のスレッドで呼び出すことができます。このシナリオでは、ローカル変数myDictに対して、このメソッドのスコープで定義されたすべての操作を同期させる必要がありますか?それとも完全に不要なのでしょうか?

+0

すべての呼び出しには、そのオブジェクトの独自のインスタンスがあり、同期の必要はありません。 –

答えて

1

一般的なルールは、マルチスレッド環境での同時アクセスからインスタンスレベルのメンバー(およびデータ)を保護することではありません。理由は非常に簡単です。マルチスレッドは別の問題です。

私のアドバイスは、アクセスの同期方法のみを知っているマルチスレッドラッパーを作ることです。そのためには、クラスの機能を公開する基本クラスまたはインタフェースが必要です。

public interface ISomeInterface 
{ 
    void MyCallBackMethod(); 
} 

public class MyClass : ISomeInterface 
{ 
    private int Data { get; set; } 
    public void MyCallBackMethod() 
    { 
     Dictionary<int, int> myDict = new Dictionary<int, int>(); 
     myDict.Add(1, 1); 
     // access this.Data - this is the part that would 
     // make problems in case of multithreaded access 
    } 
} 

public class ThreadSafe : ISomeInterface 
{ 
    private ISomeInterface Contained { get; } 
    private object SyncRoot { get; } = new object(); 

    public ThreadSafe(ISomeInterface contained) 
    { 
     this.Contained = contained; 
    } 

    public void MyCallBackMethod() 
    { 
     lock (this.SyncRoot) 
     { 
      this.Contained.MyCallBackMethod(); 
     } 
    } 
} 
+0

この場合、メソッドスコープの変数を指定すると、この基本クラスはどのように役立ちますか? –

+0

私は他の用途があると思います。ローカルスコープの変数だけでは、明らかに何かから守る理由はありません。 –

2

これはまったく必要ありません。 MyCallbackMethodが呼び出されるたびに、新しいmyDictオブジェクトがインスタンス化されます。同じインスタンスが複数のスレッドによって同時に使用された場合は、Dictionary<,>へのアクセスを保護する必要があります。

+0

私はあなたの答えの最後の部分について少し混乱しています。 MyClassが単調なクラスの場合、myDictの周りにロックをかける必要がありますか? –

+0

いいえ。「Dictionary <,>」がクラスのフィールドであった場合、そのクラスのインスタンスが複数のスレッドで使用されていた場合は、保護する必要があります。あなたの例では、メソッド内の変数です。*常に*一意のインスタンスになります – Tim

0

ローカル変数はスレッド間で共有されないため、完全に不要です。

関連する問題