複数のスレッドから符号なし整数をインクリメントしたい。
Interlocked.Increment については知っていますが、符号なし整数を処理しません。lock() を使用することもできますが、パフォーマンス上の理由から、できれば使用したくありません。
通常の方法でインクリメントするだけでスレッドセーフですか?統計にのみ使用されるため、時折のインクリメントが失われても問題ありません。私が望んでいないのは、値が破損することです。
複数のスレッドから符号なし整数をインクリメントしたい。
Interlocked.Increment については知っていますが、符号なし整数を処理しません。lock() を使用することもできますが、パフォーマンス上の理由から、できれば使用したくありません。
通常の方法でインクリメントするだけでスレッドセーフですか?統計にのみ使用されるため、時折のインクリメントが失われても問題ありません。私が望んでいないのは、値が破損することです。
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
(つまり、問題なくラップします。)
符号付き int (2^31 -1) ではなく unsigned int (2^32 - 1) の全範囲が本当に必要な場合は、int64 にキャストして (int64Interlocked.Increment
を受け取るオーバーロードがあります)、キャスト バックすることができます。 unsigned int に。
uint を volatile として宣言できます。
http://msdn.microsoft.com/en-us/library/x13ttww7(VS.71).aspx