web-dev-qa-db-ja.com

C#スレッドセーフな高速(est)カウンター

最高のパフォーマンスでC#のスレッドセーフカウンターを取得する方法は何ですか?

これは簡単です:

public static long GetNextValue()
{
    long result;
    lock (LOCK)
    {
        result = COUNTER++;
    }
    return result;
}

しかし、より高速な代替手段はありますか?

119
JohnDoDo

これはもっと簡単です:

return Interlocked.Increment(ref COUNTER);

MSDN Interlocked.Increment

214
Austin Salonen

他の人が推奨するように、Interlocked.Incrementのパフォーマンスはlock()よりも優れています。 Incrementが「バスロック」ステートメントになり、変数が直接インクリメント(x86)または「x64」に「追加」されることがわかるILとアセンブリを見てください。

この「バスロック」ステートメントは、呼び出し元のCPUが操作を実行している間、別のCPUがバスにアクセスできないようにバスをロックします。次に、C#lock()ステートメントのILを見てください。ここでは、セクションを開始または終了するためのMonitorの呼び出しが表示されます。

つまり、.Net lock()ステートメントは、.Net Interlocked.Incrementよりも多くのことを行います。

ですから、変数をインクリメントするだけなら、Interlock.Incrementが高速になります。インターロックされたすべてのメソッドを確認して、使用可能なさまざまなアトミック操作を確認し、ニーズに合った操作を見つけます。相互に関連する複数の増分/減分など、より複雑なことを行う場合、または整数よりも複雑なリソースへのアクセスをシリアル化する場合は、lock()を使用します。

102
Les

System.Threadingライブラリで.NETの組み込みインターロックインクリメントを使用することをお勧めします。

次のコードは、参照によってlong変数をインクリメントし、完全にスレッドセーフです。

Interlocked.Increment(ref myNum);

ソース: http://msdn.Microsoft.com/en-us/library/dd78zt0c.aspx

26
Andrew White

Interlocked.Increment で試してください

15
fsimonazzi