2009-11-19 4 views
5

私はこのクラスの複数のインスタンスを作りたいと思います。C#複数のクラスを使用すると複数の参照を使用して同じオブジェクトをロックできますか?

public class Worker 
{ 
    private object _lockObject; 
    private Thread _workerThread; 
    private string _name; 

    public Worker(object lockObject, string name) 
    { 
     _name = name; 
     _lockObject = lockObject; 
     _workerThread = new Thread(new ThreadStart(DoWork)); 
     _workerThread.Start(); 
    } 
    private void DoWork() 
    { 
     while(true) 
     { 
      lock(_lockObject) 
      { 
       Console.WriteLine(_name + "Doing Work"); 
      } 
     } 
    } 
} 

私はクラスの複数のインスタンスに同じロックオブジェクトを渡すと、1つのクラスのインスタンスでロックが自由になり、そのロックを待っている他のクラスのインスタンスになりますか?

static void Main() 
{ 
    private readonly object sharedLockObject = new object(); 
    Worker a = new Worker(sharedLockObject,"a"); 
    Worker b = new Worker(sharedLockObject,"b"); 
    Console.ReadLine(); 
} 

私は、上記の場合には、労働者がなることはありませんと思います: ます。Console.WriteLine(_nameが+ "仕事をしています");同時に ?

私はlock()が参照をロックするか、参照されるオブジェクトをロックするかどうか不安です。

ありがとうございました!

答えて

14

はい、objectは参照型ですので、同じオブジェクトが各ワーカーで使用されるように、同じオブジェクトへの参照を渡しています。オブジェクトは、参照ではなくロックに使用されます。

+0

おかげで「オブジェクトは、ないの参照をロックするために使用される」C#の仕様 – divinci

+1

でそれを見つけるのが大好きだ「ロック文は、指定されたオブジェクトの相互排他ロックを取得します」。 com/en-us/library/aa664735(VS.71).aspx – GraemeF

+1

'オブジェクトは参照用ではなくロック用に使用されています。彼はまた、tghisクラスの複数のインスタンス以外のコード内の他の場所から同じ共有メモリへのアクセスを同期する必要がない限り、それはクリティカルセクションだ場合 – Alexandre

4

lockステートメントは、参照変数ではなくオブジェクトインスタンスをマークします。 xが参照型のオブジェクトのインスタンスである

System.Threading.Monitor.Enter(x); 
try { 
    ... 
} 
finally { 
    System.Threading.Monitor.Exit(x); 
} 

lock(x) { 
    ... 
} 

は正確に等価です。

ので:-)はい

2

私はあなたがロックしたり、いくつかの厄介なデッドロックに入る可能性があるため使用する共有オブジェクトを渡すことではない、あなたをお勧めします。あなたは意志の仕事をやっている

public class Worker 
{ 
    private static object _syncRoot = new object(); 
    private Thread _workerThread; 
    private string _name; 

    public Worker(string name) 
    { 
     _name = name; 
     _workerThread = new Thread(new ThreadStart(DoWork)); 
     _workerThread.Start(); 
    } 
    private void DoWork() 
    { 
     while(true) 
     { 
      lock(_syncRoot) 
      { 
       Console.WriteLine(_name + "Doing Work"); 
      } 
     } 
    } 
} 
+2

... –

+0

私は、部分的にそれはすべての上に重要であるかもしれない、という点で、あなたに同意しますインスタンス。しかし、その後、再び、それはないかもしれない、とだけ彼の実装は完全に罰金になるだろう、このオブジェクトインスタンスに適用されます。 –

+0

@Charles Bretana:コード内の複数の場所から同じ共有メモリへのアクセスを同期させる必要がある場合は、クラスをその共有メモリの周りにラップし、クラスのパブリックインターフェイスを通じて同期アクセスを提供する方が良いでしょう。私はここで、ダーリンに同意します。このように同期オブジェクトを渡すことは、コードベースが大きくなるにつれて問題になります。 –

2

が、なぜWorkerクラスstatic_lockObjectメンバーをしない:ロックオンするために、クラスの静的なプライベートメンバを使用しますか?同じ効果が得られますが、よりオブジェクト指向です。

public class Worker 
{ 
    private static object _lockObject = new object(); 
    private Thread _workerThread; 
    private string _name; 

    public Worker(string name) 
    { 
     _name = name; 
     _workerThread = new Thread(new ThreadStart(DoWork)); 
     _workerThread.Start(); 
    } 
    private void DoWork() 
    { 
     while(true) 
     { 
      lock(_lockObject) 
      { 
       Console.WriteLine(_name + "Doing Work"); 
      } 
     } 
    } 
} 

EDIT:おっと!私はダーリンディミトロフの反応を見ていない。これは私がここに投稿したものと同じである。 +1、ダーリン。 http://msdn.microsoft -

関連する問題