8

次のような状況があります: オブジェクトへのアクセスを相互に除外したい。

これまでのところ、通常はロックオブジェクトを使用します

object lockObject = new object();
...

method1: lock(lockObject) { CODE1 }

現在、別のスレッドから呼び出すことができるメソッドもあります。不明な時間ブロックされるべきではなく、定義された時間内に応答する必要があります。

この場合、次のようなモニターを使用します

method2:
try{
   Monitor.TryEnter(lockObject , 20000, ref lockTaken);
   if (lockTaken) {CODE2}
}
catch(...){...}
finally
{
   if (lockTaken) Monitor.Exit(timerLock);
}

ここで私の質問は次のとおりです。ロックオブジェクトが同じで相互に排除している場合、ロックとモニターをこのように混在させることができますか、またはすべてのロックをモニターに変更する必要がありますか?

それで、同じトークンが両方とも「ロック」されますか、それともモニターはオブジェクトの別のトークンを作成してからロックしますか?

一見すると、アプリケーションが両方のコードで同時に実行されていることがわかりません。しかし、CODE1 と CODE2 が並行して実行されるタイミングの問題が存在する可能性があるかどうかはわかりません。

4

2 に答える 2

8

ロックオブジェクトが同じで相互に排除している場合、ロックと監視をこのように混在させることができます

はい、それは完全に安全であり、動作します。

ステートメントは、lock { }Monitor.Enter() および Monitor.Exit() への呼び出しに書き直されます。using() {}これは省略形であり、ステートメントと非常によく似ています。

MSDNから:

 lock (x) ...

になる

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

コメントによると、Fx4 以降では を使用できますMonitor.TryEnter()。しかし、上記の単純なバージョンがあなたの質問に答えます。

于 2013-01-17T10:50:23.080 に答える
7
lock (sync)
{
   return World();
}

中級言語でこれに沿って見ていきます。

L_0007: call void [mscorlib]System.Threading.Monitor::Enter(object)
L_000c: call int32 Hello::World()
L_0011: stloc.0 
L_0012: leave.s L_001b
L_0014: ldloc.1 
L_0015: call void [mscorlib]System.Threading.Monitor::Exit(object)

だから大丈夫なはずです。それらは技術的に同等です。

于 2013-01-17T10:53:16.333 に答える