18

複数のスレッドから符号なし整数をインクリメントしたい。

Interlocked.Increment については知っていますが、符号なし整数を処理しません。lock() を使用することもできますが、パフォーマンス上の理由から、できれば使用したくありません。

通常の方法でインクリメントするだけでスレッドセーフですか?統計にのみ使用されるため、時折のインクリメントが失われても問題ありません。私が望んでいないのは、値が破損することです。

4

6 に答える 6

45

lockパフォーマンス上の理由から使用したくないと言っていますが、テストしましたか? 争われていないロック (音からすると、そうである可能性が高い) はかなり安価です。

私は通常、スレッド化に関しては「賢く、おそらくパフォーマンスが向上する」よりも「明らかに正しい」ものを選びます (一般的に、特にスレッド化の場合)。

ロックの有無にかかわらずアプリをベンチマークし、違いに気付くことができるかどうかを確認してください。ロックが大きな違いを生む場合は、確かに、狡猾なものを使用してください。そうでなければ、私はロックに固執するでしょう。

あなたやりたいことの1つは、次のように、を使用Interlocked.Incrementしてint、必要に応じてキャストすることuintです。

using System;
using System.Reflection;
using System.Threading;

public class Test
{
    private static int count = int.MaxValue-1;

    public static uint IncrementCount()
    {
        int newValue = Interlocked.Increment(ref count);
        return unchecked((uint) newValue);
    }

    public static void Main()
    {
        Console.WriteLine(IncrementCount());
        Console.WriteLine(IncrementCount());
        Console.WriteLine(IncrementCount());
    }

}

出力:

2147483647
2147483648
2147483649

(つまり、問題なくラップします。)

于 2009-06-01T12:46:26.950 に答える
11

符号付き int (2^31 -1) ではなく unsigned int (2^32 - 1) の全範囲が本当に必要な場合は、int64 にキャストして (int64Interlocked.Incrementを受け取るオーバーロードがあります)、キャスト バックすることができます。 unsigned int に。

于 2009-06-01T12:32:30.567 に答える
-15

uint を volatile として宣言できます。

http://msdn.microsoft.com/en-us/library/x13ttww7(VS.71).aspx

于 2009-06-01T12:31:27.493 に答える