9

モニターをカーネルモードにするか、カーネル同期オブジェクトを使用する可能性のあるすべての条件のリストをコンパイルしたいと思います。

同期ブロックには、カーネル オブジェクトを参照するフィールドがあります。したがって、lock時々カーネルモードになると推測しました。

私はこれを見つけました: Lock (Monitor) internal implementation in .NET

lockしかし、回答するには質問が多すぎます。唯一の有用な情報は、OPがカーネルモードに移行することを単に述べて、OPが自分の質問に答えたことです。また、その答えをサポートするためのリンクはありません。

正確にはいつlockカーネルモードに移行しますか (かどうかではなく、理由ではなく、いつ)?

古いバージョンとの違いがある場合は、.NET 4 と 4.5 について聞くことにもっと興味があります。

リヒターの本から: 「同期ブロックには、カーネル オブジェクト、所有スレッドの ID、再帰カウント、待機スレッド カウントのフィールドが含まれています。」

4

3 に答える 3

20

これらの種類の質問のほとんどは、SSCLI20ディストリビューションから入手できるCLRソースコードを調べることで回答できます。今ではかなり古くなっています。.NET 2.0ヴィンテージですが、CLRのコア機能の多くはそれほど変更されていません。

確認するソースコードファイルはclr/src / vm/syncblk.cppです。ここでは3つのクラスが役割を果たします。AwareLockは、ロックの取得を処理する低レベルのロック実装です。SyncBlockは、ロックの開始を待機しているスレッドのキューを実装するクラスです。CLREventは、オペレーティングシステムの同期オブジェクトのラッパーです。について尋ねる。

これはC++コードであり、抽象化のレベルはかなり高いです。このコードはガベージコレクターと頻繁に相互作用し、多くのテストコードが含まれています。そこで、プロセスについて簡単に説明します。

SyncBlockには、AwareLockインスタンスを格納するm_Monitorメンバーがあります。SyncBlock :: Enter()は、AwareLock :: Enter()を直接呼び出します。まず、できるだけ安価にロックを取得しようとします。最初に、スレッドがすでにロックを所有しているかどうかを確認し、その場合はロックカウントをインクリメントします。次に、Interlocked.CompareExchange()と非常によく似た内部関数であるFastInterlockCompareExchange()を使用します。ロックが競合しない場合、これは非常に迅速に成功し、Monitor.Enter()が戻ります。そうでない場合は、別のスレッドがすでにロックを所有しており、AwareLock::EnterEpilogが使用されます。CLREventが使用されるように、オペレーティングシステムのスレッドスケジューラを関与させる必要があります。必要に応じて動的に作成され、WaitOne()メソッドが呼び出されます。これにはカーネルの移行が含まれます。

したがって、質問に答えるには十分です。ロックが競合し、スレッドが待機する必要がある場合、Monitorクラスはカーネルモードに入ります。

于 2013-02-17T17:09:31.747 に答える
4

ロックの競合が激しい場合。

ロックの競合が軽い場合は、ロックが再び解放されるまで待機するための迅速な CPU スピンロックがあります。スレッドおよびその他のそのような管理を中断するためのカーネル モード呼び出し。

于 2013-02-17T16:37:30.160 に答える
0

スピンウェイト ステップの後、シングル コア マシンでスピンウェイトをスキップするなど、追加のインテリジェンスが存在する可能性があります。

于 2013-02-17T15:27:50.227 に答える