2011-09-03 18 views
6

私は、次のC#クラスに同じオブジェクトを呼び出す複数のスレッドが同時に機能します。それは問題を引き起こすことができますか?

class MyClass 
{ 
    private int _i; 
    private object _locker = new object(); 

    public void DoSomething() 
    { 
     var b = 2; 

     // some work that depends on b being 2 

     lock(_locker) 
     { 
      _i = 3; 
     } 

     // some more work 

     b = -1; 

     // some more work 
    } 
} 

を持っていると私はそれをこのように使用すると仮定し、

//Usage: 

var myobject = new MyClass(); 
new Thread(new ThreadStart(() => myobject.DoSomething())).Start(); 
new Thread(new ThreadStart(() => myobject.DoSomething())).Start(); 

には、以下のシーケンスが起こることはできますか?

Thread 1 is halfway through its work. 
Thread 2 just starts. Sets b = 2. 
Thread 1 sets b = -1. 
Thread 2 is confused because it expected b to be 2 but its -1. 

重要な点は、bがローカル変数であるということです。 2つのスレッドがbの同じインスタンスにアクセスできますか?私は、インスタンス変数_iの場合、これが起こることを理解しています。したがって、そのためのlockの構成。しかし、ローカル変数のロックを行う必要があるかどうかはわかりません。

+1

「b」はローカルであり、したがって各スレッドに固有です。 –

+1

'_i'に同じ値を2回だけ割り当てた場合、スレッドを開始する前に非並行コードで代入を移動することを検討してみませんか? (または終了時に) –

答えて

11

呼び出し元がメソッドDoSomething()を入力すると、ローカル変数がスタックに配置されます。各スレッドは個別のスタック上で動作し、固有のローカル変数を取得します。 Wikipedia for thread local storageから

この部分はC#もスレッドに適用される:すなわち

、静的またはグローバル変数のデータが常に正常 からスレッドによって参照される同じメモリロケーションに位置 、あります同じプロセス。しかし、スタック上の変数は、各スレッドが独自のスタックを持ち、別のメモリに存在するので、 の位置にあるスレッドに対してローカルです。

+2

私の例では、 'b'はプリミティブ型です。しかし、 'b'はあるクラスのオブジェクトだとします。私はその財産を変更しています。今、 'b'は参照型ですが、それはまだ各スレッドのローカルスタックにありますか?私は参照型オブジェクトがすべてのスレッドによって共有されているヒープメモリに格納されていると思った... –

+3

@Amith:メソッド内でオブジェクトを作成すると*オブジェクト参照はスタックに格納され、オブジェクト自体は割り当てられますヒープ上に。基本的には、各スレッドはヒープ上の別のオブジェクトへの独自のオブジェクト参照を持つため、これは何も変更されません。 – BrokenGlass

+0

bが参照型で、メソッドのパラメータとしてメソッドに渡された場合はどうなりますか? – Harindaka

関連する問題