回答:
すばらしい質問です。私は間違っているかもしれません。試してみましょう。私の元の回答のリビジョン#2 ..もう少し理解してください。読んでくれてありがとう:)
ロック(obj)
モニター
ロックまたはモニターの使用は、コードのスレッド依存ブロックの同時実行を防ぐのに役立ちますが、これらの構造では、あるスレッドが別のスレッドとイベントを通信させることはできません。これには同期イベントが必要ですは、シグナルと非シグナルの2つの状態のいずれかを持ち、スレッドのアクティブ化と一時停止に使用できるオブジェクトです。ミューテックス、セマフォはOSレベルの概念です。たとえば、名前付きミューテックスを使用すると、複数の(管理された)exe間で同期できます(マシンでアプリケーションのインスタンスが1つだけ実行されていることを確認します)。
ミューテックス:
セマフォ(私の脳を傷つけます)。
Monitor
はコミュニケーションを許可しないと主張しています。することができますそれでもPulse
などとMonitor
「その他の.Net同期クラスの使用」について-あなたが知っておくべきその他のいくつか:
また、CCR / TPL(Parallel Extensions CTP)にはより多くの(オーバーヘッドの少ない)ロック構造がありますが、IIRCは.NET 4.0で利用できるようになります。
ECMAで述べられているように、Reflectedメソッドから確認できるように、lockステートメントは基本的に以下と同等です。
object obj = x;
System.Threading.Monitor.Enter(obj);
try {
…
}
finally {
System.Threading.Monitor.Exit(obj);
}
前述の例から、モニターがオブジェクトをロックできることがわかります。
Mutexe は文字列識別子をロックできるため、プロセス間同期が必要な場合に役立ちます。異なるプロセスが同じ文字列識別子を使用して、ロックを取得できます。
セマフォはステロイドのミューテックスに似ており、同時アクセスの最大数を提供することで同時アクセスを可能にします。制限に達すると、セマフォは、呼び出し元の1人がセマフォを解放するまで、リソースへのそれ以上のアクセスをブロックし始めます。
DotGNUでのクラス化とスレッド化のCLRサポートを行い、いくつかの考えがあります...
クロスプロセスロックが必要でない限り、ミューテックスとセマフォの使用は常に避けてください。.NETのこれらのクラスは、Win32ミューテックスとセマフォのラッパーであり、かなり重い(カーネルへのコンテキストスイッチが必要で、特にロックが競合していない場合)。
他の人が言及しているように、C#ロックステートメントはMonitor.EnterおよびMonitor.Exit(try / finally内に存在)のコンパイラーマジックです。
モニターには、Monitor.Pulse / Monitor.Waitメソッドを介したMutexesにはないシンプルだが強力なシグナル/待機メカニズムがあります。Win32で同等のものは、CreateEventを介したイベントオブジェクトで、実際には.NETにWaitHandlesとしても存在します。Pulse / Waitモデルは、Unixのpthread_signalおよびpthread_waitに似ていますが、競合しないケースでは完全にユーザーモードの操作になるため、より高速です。
Monitor.Pulse / Waitの使い方は簡単です。1つのスレッドで、オブジェクトをロックし、フラグ/状態/プロパティを確認します。それが予期したものでない場合は、Monitor.Waitを呼び出してロックを解除し、パルスが送信されるまで待機します。待機が戻ると、ループバックしてフラグ/状態/プロパティを再度確認します。他のスレッドでは、フラグ/状態/プロパティを変更するたびにオブジェクトをロックし、PulseAllを呼び出してリスニングスレッドを起動します。
多くの場合、コードにロックを設定するために、クラスをスレッドセーフにする必要があります。ただし、多くの場合、クラスは1つのスレッドによってのみ使用されます。これは、ロックによってコードが不必要に遅くなることを意味します...これは、CLRの賢い最適化がパフォーマンスの向上に役立つ場所です。
Microsoftのロックの実装についてはわかりませんが、DotGNUとMonoでは、すべてのオブジェクトのヘッダーにロック状態フラグが格納されています。.NET(およびJava)のすべてのオブジェクトはロックになる可能性があるため、すべてのオブジェクトはヘッダーでこれをサポートする必要があります。DotGNU実装には、ロックとして使用されるすべてのオブジェクトにグローバルハッシュテーブルを使用できるフラグがあります。これには、すべてのオブジェクトの4バイトのオーバーヘッドを排除できるという利点があります。これはメモリ(特にスレッド化されていない組み込みシステム)には適していませんが、パフォーマンスに影響を与えます。
MonoとDotGNUは、ミューテックスを効果的に使用してロック/待機を実行しますが、スピンロックスタイルの比較および交換操作を使用して、本当に必要でない限り、実際にハードロックを実行する必要をなくします。
モニターを実装する方法の例を以下に示します。
http://cvs.savannah.gnu.org/viewvc/dotgnu-pnet/pnet/engine/lib_monitor.c?revision=1.7&view=markup
可能であれば、「lock()」、「Mutex」、「Monitor」を回避しようとします...
.NET 4の新しい名前空間System.Collections.Concurrentを確認してください。
スレッドセーフなコレクションクラスがいくつかあります。
http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx
ConcurrentDictionaryロック!もう手動ロックは不要です!
ほとんどの場合、ロック(=モニター)やミューテックス/セマフォは使用しないでください。それらはすべて現在のスレッドをブロックします。
また、クラスは絶対に使用 System.Collections.Concurrent
しないでください。複数のコレクション間のトランザクションをサポートせず、現在のスレッドをブロックしないため、クラスは競合状態の主な原因になります。
驚いたことに、.NETには同期のための効果的なメカニズムがありません。
C#にGCD(world)からのシリアルキューを実装しましたObjc/Swift
-非常に軽量で、スレッドプールを使用する同期ツールをブロックせず、テストを行います。
ほとんどの場合、データベースアクセス(hello sqlite)からビジネスロジックまで、あらゆるものを同期するための最良の方法です。