1

この相互排除のパターンは、私が思うほど安全ですか?もしそうなら、あなたはそれを何と呼びますか?

lock (_lock) {
    if (_flag) return;
    else _flag = true;
}
try {
    //critical code...
}
finally {
    _flag = false;
}

クリティカルセクションを確保したいのですが、他のスレッドがロックを取得するのを待って積み重なることはありません。明らかに、私はフラグが他のどこにも設定されていないことを確認します。もっと良い方法はありますか?

4

4 に答える 4

14

いいえ、それは安全ではありません。ブロックせずに相互に排他的であることを確認したい場合は、Monitor.TryEnterを使用できます。

if (Monitor.TryEnter(lockObj, 0)) {
    // got the lock !
    try {
        // code
    }
    finally { // release the lock
        Monitor.Exit(lockObj);
    }
}
于 2009-02-16T14:41:00.360 に答える
5

見たことがありMonitor.TryEnterますか?

于 2009-02-16T14:40:57.647 に答える
3

相互排除パターンの正確さは、割り当て _flag=false がアトミックであるかどうかによって異なります。割り当てが別のスレッドによって中断される可能性がある場合に何が起こるか想像してみてください。割り当ての中間結果がテストによって false と解釈される可能性がある場合、1 つの割り当てによって複数のスレッドがクリティカル セクションに入る可能性があります。

相互排除パターンの正確性は、ステートメントの順序を再配置する可能性があるコンパイラーの最適化がないことにも依存します。間にあるコードでは _flag が参照されないため (そして、間にあるコードは例外をスローしないため)、割り当て _flag=false を上に移動する "スマート" コンパイラを想像してみてください。次に、コンパイラはロックセクションの部分を最適化して読み取ることができます

if(_flag) return;

パターンが失敗する可能性がある理由の両方の例は、非常に推測に基づくものであり、それが機能すると想定しても問題ないと思います。ただし、必要に応じて機能する別のオプションが存在する場合は、それを使用することをお勧めします (他の投稿を参照)。同じコードに他の開発者がいる場合、パターンが機能するかどうかを考慮する必要はありません。

于 2009-02-16T22:15:20.427 に答える
0

簡単なlock(Object)文でうまくいきませんか?バックグラウンドで、ブロックMonitor内にクリティカル セクションを作成します。try... finally

private static readonly Object lockMe = new Object();
lock(lockMe)
{
    // critical code
}
于 2009-02-16T15:24:48.900 に答える