1

適切に理解できないコードが少しあります。問題は、プログラムがマルチスレッド化されており、同期する必要があるコードが少しあるため、次のように記述したことです。

lock (lockObject)
{
   if (!Monitor.TryEnter(lockObject))
     Monitor.Wait(lockObject);

   //do stuff...
   Monitor.PulseAll(lockObject);
}
Monitor.Exit(lockObject);

私が抱えている問題は、ある時点ですべてのスレッドがスリープしているように見えることです-誰かが理由を教えてもらえますか? プログラムはほとんど CPU を消費せずに無限に実行され続けますが、作業は行われません。私はエラーがほとんど(開発者の場合-常に)モニターの前0.5mにあることを知っています-しかし、私はそれを自分で理解することはできません...おそらく数分で;)

誰かが私にそれを説明してもらえますか - 前もって感謝します。

4

3 に答える 3

3

最初の lock ステートメントはタイプミスであり、lock(lockObject) (小文字) を意味していると思います。

ここでロックを少し誤解していると思います。コード内の if ブロックが true になることはありません。その理由は、lock(lockObject) が実際には次のように拡張されるためです。

Monitor.Enter(lockObject);
try {
...
} finally{ 
Monitor.Exit(lockObject);

そのため、if ブロックをヒットするまでに、既にロックを所有しており、TryEnter は常に成功するはずです。

于 2009-03-13T13:22:53.950 に答える
1

それは奇妙な設定です。「LockObject」は「lockObject」と同じですか? それともタイプミスですか?それらが同じである場合、既にロックしているものに対して Monitor.TryEnter を呼び出す必要がないため、セットアップは冗長です。「LockObject」が別のオブジェクトである場合、Monitor.Exit を lock ステートメント内に移動してみませんか?

于 2009-03-13T13:25:55.097 に答える
1

と の間に違いはLockObjectありlockObjectますか? それは明らかではありません...

でも!それらが異なるオブジェクトである場合、最初に:Wait持っていないロックを使用することはできません...そしてTryEnter、タイムアウトを指定した場合にのみ false を返します。そのコードは正確に何をしようとしていますか?

PulseAllこれ以上のコンテキストがなければ、とWaitが何をするように設計されているかは完全には明らかではありません。たとえば、ここでは、キューがいっぱいになったときにキューをブロックしたり ( Wait)、スペースが利用可能になったときにキューを解放したりするために使用されます ( PulseAll)。

必要なだけのように思えます:

lock (lockObject)
{
    // do stuff
}

私が見ることができる差し迫った問題が 2 つあります。まず、取得したロック (つまり、例外) を常に解放することが明らかではありません。lockforだけを使用してみてくださいEnter/Exit- それは正しくなります。

2番; すべてのスレッドが呼び出した場合Wait... 誰がスレッドを起こしますか? 彼らは何を待っていますか?提示されたとおり: はい、それらはすべて無期限にスリープ状態になります。

于 2009-03-13T13:23:36.990 に答える