请考虑以下代码:
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是否会获得锁定?考虑两个锁都使用相同的锁定对象。
答案 0 :(得分:5)
不,线程B需要等到线程A释放锁定。这就是它是同一个锁对象的重点 - 毕竟还有一个锁。获取或释放锁定无关紧要:一次只能有一个线程“拥有”监视器。
顺便说一句,我会强烈建议你使用大括号来提高可读性:
lock(_list)
{
_list.Add(...);
}
答案 1 :(得分:2)
不,因为它们使用相同的锁定对象,所以它们是互斥的。
通常,代码用于锁定对象(例如列表)以对其执行操作,而不会受到其他线程的干扰。这要求无论执行什么操作,项目都会被锁定。
详细说明,假设您有一个设计为线程安全的列表。如果您尝试同时添加和删除多个项目,则可能会损坏列表。通过在需要修改时锁定列表,可以帮助确保线程安全。
这一切都取决于一个对象将使所有锁互斥。
答案 2 :(得分:2)
作为旁注,您不应该锁定列表本身,而应该锁定在专门为此目的创建的object
上。
答案 3 :(得分:1)
如果线程A正在使用锁,那么没有其他线程可以使用它(无论锁在何处使用)。因此,线程B将被阻止,直到该锁定为空。
答案 4 :(得分:1)
考虑一下:
lock(obj)
{
//Do Stuff;
}
简写:
Monitor.Enter(obj);
try
{
//Do Stuff;
}
finally
{
Monitor.Exit(obj);
}
现在考虑Monitor.Enter()
是一个方法调用,就像任何其他方法一样。它对所调用的代码中的位置一无所知。它唯一知道的是传递给它的对象。
就你而言,你所谓的“锁1”和“锁2”是同一个锁。