3

次のコードを検討してください。

static void AddItem()
{
    lock (_list) 
        _list.Add ("Item " + _list.Count); //Lock 1

    string[] items;
    lock (_list) 
        items = _list.ToArray(); //Lock 2
    foreach (string s in items) 
        Console.WriteLine (s);
}

スレッドAがロック2を取得し、スレッドBがロック1を取得しようとした場合、Bはロックを取得しますか?両方のロックが同じロックオブジェクトを使用していることを考慮してください。

4

5 に答える 5

5

いいえ、スレッドBはスレッドAがロックを解除するまで待つ必要があります。それが同じロックオブジェクトであるという点です。結局のところ、1つのロックがあります。ロックが取得または解放される場所は関係ありません。一度に1つのスレッドのみがモニターを「所有」できます。

ちなみに、読みやすくするために中かっこを使用することを強くお勧めします。

lock(_list)
{
    _list.Add(...);
}
于 2012-08-14T12:50:48.730 に答える
2

いいえ、同じロックオブジェクトを使用するため、相互に排他的です。

多くの場合、コードは、他のスレッドからの干渉なしにオブジェクト(リストなど)をロックして操作を実行するために使用されます。これには、実行される操作に関係なく、アイテムがロックされている必要があります。

詳述すると、スレッドセーフになるように設計されたリストがあるとします。複数のアイテムを同時に追加および削除しようとすると、リストが破損する可能性があります。リストを変更する必要があるときはいつでもリストをロックすることで、スレッドセーフを確保するのに役立ちます。

これはすべて、1つのオブジェクトがすべてのロックを相互に排他的にするという事実に依存します。

于 2012-08-14T12:51:07.373 に答える
2

いいえ、Bはしません。両方が同じオブジェクトをロックしているため、2つのロックは「リンク」されています。このため、このようなコードを高度に最適化する必要がある場合は、複数のロックオブジェクトを検討することがあります。

ちなみに、リスト自体ではなく、objectその目的のために特別に作成されたものをロックする必要があります。

于 2012-08-14T12:51:53.503 に答える
1

スレッドAがロックを使用している場合、他のスレッドはそれを使用できません(ロックが使用されている場所に関係なく)。したがって、スレッドBは、そのロックが解放されるまでブロックされます。

于 2012-08-14T12:52:03.410 に答える
1

次のことを考慮してください。

lock(obj)
{
 //Do Stuff;
}

略記:

Monitor.Enter(obj);
try
{
  //Do Stuff;
}
finally
{
  Monitor.Exit(obj);
}

Monitor.Enter()これが他のメソッド呼び出しと同じであると考えてください。コードのどこで呼び出されたかについては何も知りません。それが知っている唯一のことは、どのオブジェクトがそれに渡されたかです。

それに関する限り、あなたが「ロック1」と「ロック2」と呼ぶものは同じロックです。

于 2012-08-14T13:10:05.440 に答える