C#のマルチスレッド符号なしインクリメント
-
06-09-2019 - |
質問
私は、複数のスレッドから符号なし整数をインクリメントします。
私はInterlocked.Incrementについて知っているが、それは、符号なし整数を処理しません。私は()ロックを使用することができますが、私はパフォーマンス上の理由から、可能であれば、むしろないでしょう。
はそれだけで通常の方法でそれをインクリメントするスレッドセーフですか?時折増分が失われてしまった場合には、統計情報だけのために使われているように、それは、問題ではないだろう。私はしたくないことは壊れるする値です。
解決
あなたは、パフォーマンス上の理由からlock
を使用したくないと言う - しかし、あなたはそれをテストしていますか? (これはそれの音によって、である可能性が高い)無競争のロックはかなり安いです。
それは(と一般的には、しかし、特にスレッドのために)スレッドに来るとき、私は一般的に「明らかに正しい」というより「賢いとおそらくより良いパフォーマンス」のために行く。
ベンチマークとし、ロックせずにアプリを、そしてあなたも違いに気づくことができるかどうかを参照してください。ロックは、その後必ず、の重要の違いを行った場合、狡猾なものを使用します。そうでなければ、私はちょうどロックに固執すると思います。
は、を一つのことがやりたいかもしれませんが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
(換言すれば、それは問題なくラップ。)
他のヒント
あなたが本当にunsigned int型の全範囲を必要とする場合(2 ^ 32から1)ではなく署名したint型(2 ^ 31 -1)よりも、あなたは(Int64型をとるInterlocked.Increment
のオーバーロードがあります)int64型にキャストできその後、unsigned int型にキャストバックます。
符号付き整数の2の補数表現を使用するシステムでは( )ウィキペディアによれば、符号なし整数をインクリメントするビットの同じセットを使用して表す符号付き整数をインクリメントするのと同じ効果を有します。このように、人は何を犠牲にすることなく、符号なし整数でInterlockedIncrementを使用することができます。
例えば、3ビットで、我々は以下の表を持っています
raw bits | unsigned integer | twos complement signed integer
------------------------------------------------------------
000 | 0 | 0
001 | 1 | 1
010 | 2 | 2
011 | 3 | 3
100 | 4 | -4
101 | 5 | -3
110 | 6 | -2
111 | 7 | -1
1ずつ増加(及びアカウントにオーバーフローをとる)の両方の場合において、テーブル内の1つのエントリを下に移動することと等価です。ものが算術を補完するためのネガを逆の順序で配置されているため、これは、動作しないことに注意してください。
あなたは揮発性としてUINTを宣言することができます。
http://msdn.microsoft.com /en-us/library/x13ttww7(VS.71).aspxする