lock(objlocker)は、そのオブジェクトをスレッドセーフなアプリにしますか?そして、静的メンバーは自動的にスレッドセーフですか?
-
07-07-2019 - |
質問
オブジェクトをロックすると、そのオブジェクトはアプリケーション全体でロックされますか?
たとえば、C#3.0のNutshellセクション19.6.1"スレッドセーフティと.NET Frameworkタイプ"のスニペット:
static void AddItems( )
{
for (int i = 0; i < 100; i++)
lock (list)
list.Add ("Item " + list.Count);
string[] items;
lock (list) items = list.ToArray( );
foreach (string s in items) Console.WriteLine (s);
}
最初のロックを行います:
lock (list)
list.Add ("Item " + list.Count);
別のスレッドがアクセスしないようにします:
lock (list) items = list.ToArray( );
または両方を同時に実行できますか?
CLRは静的メソッドを自動的にスレッドセーフにしますか?それとも開発者次第ですか?
ありがとう、 ジョン
解決
class UsefulStuff {
object _TheLock = new object { };
public void UsefulThingNumberOne() {
lock(_TheLock) {
//CodeBlockA
}
}
public void UsefulThingNumberTwo() {
lock(_TheLock) {
//CodeBlockB
}
}
}
CodeBlockA
と CodeBlockB
は、両方が同じオブジェクトインスタンス _TheLock
でロックされているため、異なるスレッドで同時に実行できません。 。
_TheLock
自体のメソッドは完全に影響を受けません。
他のヒント
注意すべきもう1つの点は、静的コンストラクターがランタイムによってスレッドセーフな方法で実行されることです。シングルトンを作成し、それを次のように宣言する場合:
public class Foo
{
private static Foo instance = new Foo();
public static Foo Instance
{
get { return instance; }
}
}
その後、スレッドセーフになります。ただし、新しいFooをインスタンスゲッターの内部にインスタンス化する場合は、独自のスレッドセーフを記述する(つまり、オブジェクトをロックする)必要があります
CLRは、静的メソッドを自動的にスレッドセーフにしません。あなたは自分でそれをしなければなりません。
lock(list)はそのオブジェクトをロックとして使用するため、別のスレッドが(同じ「リスト」オブジェクトを持つ)lock(list)で別のポイントに到達すると、他のスレッドは最初のスレッドがロックを解除するまでブロックします。
明確にするために、lock(foo)はfooオブジェクトに「ロック」しないで、fooオブジェクトに関連付けられたロックを取得して、クリティカルセクション(構造内のステートメント&quot; lock(o)stmt&quot ;)現在のスレッドがロックを取得したときにのみ実行されます。