【问题标题】:Multiple code blocks locked by the same object多个代码块被同一个对象锁定
【发布时间】:2011-10-20 10:24:36
【问题描述】:
如果我有这样的事情:
private readonly object objectLock = new object();
public void MethodA()
{
lock(objectLock)
{
//do something
}
}
public void MethodB()
{
lock(objectLock)
{
//do something
}
}
如果我有 2 个线程并且两个线程同时进入,第一个线程调用 MethodA 和第二个方法 B。无论哪个先到达那里并锁定 objectLock,我假设另一个线程坐在那里等到 objectLock 不再被锁定。
【问题讨论】:
标签:
c#
.net
multithreading
c#-4.0
【解决方案1】:
是的,您的解释是正确的——除非锁已经被占用(在这种情况下,两个线程都在等待,并且任意线程在解锁后立即获得锁)。
(有点题外话)如果他们正在做一些不平凡的事情,我建议不要锁定整个方法。尽量保持代码的“锁定”部分尽可能小和尽可能快。
【解决方案2】:
没错。
然而,被锁定的不是 objectLock(也不是对象),而是被锁定的代码块。
将传递给lock 关键字的对象想象成一把可以解锁多扇门但一次只能访问一个房间的钥匙。
【解决方案3】:
你完全正确!但要小心锁。锁可能会让你的程序线程安全(意味着并发访问时不会出错),但要让你的程序真正利用在多内核系统上运行需要付出更多的努力。
【解决方案4】:
是的,你是对的,因为 Monitor.Enter 和 Monitor.Exit 在场景后面的同一个对象 objectLock 上被调用。记住它是同步的代码块而不是 objectLock。
【解决方案5】:
你是对的。如果这是不可取的,那么考虑一下:
lock(objectLock)
{
//do something
}
相当于:
Monitor.Enter(objectLock);
try
{
//do something
}
finally
{
Monitor.Exit(objectLock);
}
您可以将其替换为:
if(Monitor.TryEnter(objectLock, 250))//Don't wait more than 250ms
{
try
{
//do something
}
finally
{
Monitor.Exit(objectLock);
}
}
else
{
//fallback code
}
还值得看看TryEnter() 的重载,以及其他同步对象,例如ReaderWriterLockSlim。