1

以下のコードは、私が達成しようとしていることの非常に単純化された例です。

 private object _highestLevelLock = new object();
    private int _highestValue;
    private void SetHighestValue()
    {
        var random = new Random();
        var next = random.Next(0, 100);
        if (next > _highestValue)
        {
            lock (_highestLevelLock)
            {
                if(next > _highestValue)
                    _highestValue = next;
            }
        }
    }

つまり、これまでに遭遇した最大の整数を保持する変数があります。SetHighestValue() は、複数のスレッドからアクセスできます。

生成されたランダムな整数が現在最大の整数よりも大きい場合、_highestValue を更新します。

私の質問は、next>highestValue の場合に 2 回チェックしないようにするにはどうすればよいですか? ロック内から削除すると、このスレッドが値を設定する前に _highestValue がさらに高い値に設定されるリスクがあり、このシナリオでは _highestValue が不正確になります。

ロックの外側にある if ステートメントを削除できることはわかっていますが、不必要にロックしたくありません。

これを達成するためのより良い方法はありますか?ロックおよび/またはインターロックされた名前空間の使用の潜在的な組み合わせ?

やや関連する注意事項として、_highestValue は揮発性である必要がありますか? たとえそうであったとしても、当面の私の質問には役立たないと思います。

ありがとう!

4

2 に答える 2

2

あなたが説明しているのは、テストとテストとセットのケースであり、物事を処理する非常に効率的な方法です。あなたの質問に答えるために、条件を関数にカプセル化する以外に、コードの重複を取り除く方法はありません。

于 2012-10-01T22:47:09.410 に答える
1

ロックの代わりにクラスを使用できると思いますInterlocked: より高い値を持つ各スレッドは更新を実行しようとしますが、失敗した場合は再チェックします:

var next = random.Next(0, 100);
int current = _highestValue;
bool updated = false;
while(next > current && !updated)
{
    updated = Interlocked.Exchange(ref _highestValue, next, current);
    current = _highestValue;
}
于 2012-10-01T22:50:46.380 に答える