複数のスレッドから同時にアクセスされる変数がdecimal
です。 Interlocked
クラス関数は小数点をまったくサポートしていないので、残っている唯一のアプローチはlock(){}
です。それは過労だと思われる。スレッドセーフな方法で10進数をインクリメント(値を加算)する方法はありますか?
decimal
変数に値をスレッドセーフな方法で追加する方法はありますか?
複数のスレッドから同時にアクセスされる変数がdecimal
です。 Interlocked
クラス関数は小数点をまったくサポートしていないので、残っている唯一のアプローチはlock(){}
です。それは過労だと思われる。スレッドセーフな方法で10進数をインクリメント(値を加算)する方法はありますか?
decimal
変数に値をスレッドセーフな方法で追加する方法はありますか?
ロックを使用することは過度の攻撃ではありません。 が必要ですです。
System.Decimalのような構造型は決してアトミックではなく、ネイティブのCPUワードサイズにも適合しません。 Interlockedにはそのためのオーバーロードもありません。
いいえdecimal
の内部表現は、CPUレベルでアトミック命令で変更するには複雑すぎます(これはほとんどの場合Interlocked
であり、興味のあるものです)。
CPUが原子的に何らかの量を処理できない場合、手動ロックが唯一のオプションです。同期プリミティブ(たとえばlock
とmutex)を選択できますが、それだけです。
InterLocked
を使用できますが、小数点をInt64
に変換する必要があります。コンバージョンでは、小数点以下の桁数を精度のために保持する必要があります。
//Declare up front accessible from all threads
Int64 totalAmount = 0;
//Inside the thread you do this
var amount = (Int64)(decimalAmount * 10000); //10.000 is to preserve 4 decimal places
Interlocked.Add(ref totalAmount, amount);
//After all threads have finished, go back to decimal type.
var totalDecimalAmount = totalAmount/10000;
はあなたが保存したいと思いますどのように多くの小数点以下の桁に応じて、精度を失うことに注意してください:たとえば、あなたは小数点以下4桁を維持したいので、あなたはこのような何かを行うことができます。 Decimal.MaxValue
は79,228,162,514,264,337,593,543,950,335
であり、Int64.MaxValue
は9,223,372,036,854,775,807
である。だから非常に大きな数字は合わないでしょう。 Int64型がオーバーフローする前に、最大の数を小数点以下4桁を維持することが、ここでの数字は10億の上に行くことは決してありませんし、私はInterlocked
を使用すると、この方法は、その後、Parallel.Forループに高速であることを確信しているように私はそれをこのように使用9,223,372,036,854,775,807/10000 = 922,337,203,685,477
ですlock
またはmutexを使用します。あなたがオブジェクトでラップdecimal
として合計を維持する気にしない場合は
は、あなたがこのアプローチを使用できます。このアプローチは、ロックを使用しませんが
private static object myTotal = 0M;
static void InterlockedAddTotal(decimal val) {
object next;
object current;
do {
current = myTotal;
next = val + (decimal)current;
} while (Interlocked.CompareExchange(ref myTotal, next, current) != current);
}
を、それが運ぶオブジェクトにdecimal
をラップそれ自体のパフォーマンスに影響します。状況によっては、ロックを使用するほうが安いかもしれません。