スレッドセーフではないオブジェクトを使用するためには、コードを次のようなロックでラップする必要があります。
private static readonly Object obj = new Object();
lock (obj)
{
// thread unsafe code
}
そのため、複数のスレッドが同じコードにアクセスするとどうなりますか(ASP.NET Webアプリケーションで実行されているとします)。彼らはキューに入っていますか?もしそうなら彼らはどのくらい待つのだろうか?
ロックを使用することによるパフォーマンスへの影響は何ですか?
lock
ステートメントは、C#3.0によって次のように翻訳されました。
var temp = obj;
Monitor.Enter(temp);
try
{
// body
}
finally
{
Monitor.Exit(temp);
}
C#4.0 これは変更されました そして今それは次のように生成されます:
bool lockWasTaken = false;
var temp = obj;
try
{
Monitor.Enter(temp, ref lockWasTaken);
// body
}
finally
{
if (lockWasTaken)
{
Monitor.Exit(temp);
}
}
Monitor.Enter
が何をするのかについてのより多くの情報を見つけることができます ここ 。 MSDNを引用するには:
Enter
を使用して、パラメータとして渡されたオブジェクトのモニタを取得します。他のスレッドがそのオブジェクトに対してEnter
を実行したが、対応するExit
をまだ実行していない場合、現在のスレッドは他のスレッドがオブジェクトを解放するまでブロックします。同じスレッドがブロックせずにEnter
を複数回呼び出すことは正当です。ただし、オブジェクトを待機している他のスレッドがブロックを解除する前に、同数のExit
呼び出しを呼び出す必要があります。
Monitor.Enter
メソッドは無限に待機します。それは ではない タイムアウトします。
あなたが思うよりも簡単です。
Microsoft による:lock
キーワードは、他のスレッドがクリティカルセクションにある間、1つのスレッドがコードのクリティカルセクションに入らないようにします。別のスレッドがロックされたコードを入力しようとすると、オブジェクトが解放されるまで待機し、ブロックされます。
lock
キーワードは、ブロックの先頭で Enter
を呼び出し、ブロックの最後で Exit
を呼び出します。 lock
キーワードは実際にはバックエンドで Monitor
クラスを処理します。
例えば:
private static readonly Object obj = new Object();
lock (obj)
{
// critical section
}
上記のコードでは、最初にスレッドがクリティカルセクションに入り、次にobj
をロックします。別のスレッドが入ろうとすると、obj
もロックしようとします。これは最初のスレッドによってすでにロックされています。最初のスレッドがobj
を解放するのを待つ必要があります。最初のスレッドが離れると、別のスレッドがobj
をロックしてクリティカルセクションに入ります。
いいえ、彼らは並んでいません、彼らは寝ています
次の形式のロック文
lock (x) ...
ここで、xは参照型の式です。これは、とまったく同じです。
var temp = x;
System.Threading.Monitor.Enter(temp);
try { ... }
finally { System.Threading.Monitor.Exit(temp); }
あなたはただそれらがお互いを待っていることを知る必要があります、そして1つのスレッドだけがブロックをロックするために入るでしょう、他は待つでしょう...
Monitorは十分に高速なので.netで書かれているので、 クラスMonitor with リフレクター を見てください。
ロックは、他のスレッドがロックブロックに含まれるコードを実行するのをブロックします。ロックブロック内のスレッドが完了してロックが解放されるまで、スレッドは待機する必要があります。これは、マルチスレッド環境でのパフォーマンスに悪影響を及ぼします。これを行う必要がある場合は、ロックブロック内のコードが非常に迅速に処理できるようにする必要があります。データベースへのアクセスなどの費用のかかる活動を避けるようにしてください。
パフォーマンスへの影響は、ロック方法によって異なります。あなたはここで最適化の良いリストを見つけることができます: http://www.thinkingparallel.com/2007/07/31/10-ways-to-reduce-lock-contention-in-threaded-programs/ /
基本的には、待機中のコードをスリープさせるので、できるだけロックしないようにしてください。あなたがロックの中にいくつかの重い計算または長続きするコード(例えばファイルアップロード)があるならば、それは多大なパフォーマンス損失をもたらします。
Lockステートメント内の部分は1つのスレッドでしか実行できないため、他のすべてのスレッドはロックを保持しているスレッドが終了するまで無期限に待機します。これにより、いわゆるデッドロックが発生する可能性があります。
lock
ステートメントは、 Enter
のExit
およびMonitor
メソッドの呼び出しに変換されます。
lock
ステートメントは、ロックオブジェクトが解放されるのを無期限に待ちます。