2012-11-01 11 views
78

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

これは、それを取得するのと同じくらい簡単です:

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

しかし、そこに高速の選択肢がありますか? Interlocked.Increment

答えて

138

20

私はあなたがSystem.Threadingライブラリに.NETのインターロックの増分で構築を使用することをお勧め。

次のコードは、参照することにより、長い変数をインクリメントし、完全にスレッドセーフされています

Interlocked.Increment(ref myNum); 

出典:http://msdn.microsoft.com/en-us/library/dd78zt0c.aspx

66

他の人が推奨されているように、Interlocked.Incrementlock()よりも優れた性能を持っています。 Incrementが "バスロック"ステートメントに変わり、変数が直接増分(x86)または "追加"されて(x64)と表示されるILとアセンブリを見てみましょう。

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

つまり、.Net lock()の文は.Net Interlocked.Incrementより多くのことを行っています。

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

+0

実装の詳細については、コンテキスト – fsimonazzi

+0

-1を追加するためのUpvote。ロックはアトミックなopより遅いですが、これはILとは関係ありません。これらの関数呼び出しは、本来的にILに要求されていないセマンティクスでない場合、アトミックオペレーションよりも高速です。 – Puppy

関連する問題