实现锁定时,我曾经在我的类中创建一个私有对象:
如果我想确保它在创建我的类的线程中被锁定:
private object Locker = new object();
如果我想确保它将被我的应用程序中的所有线程锁定:
private static object Locker = new object();
但是在这里: Why does the lock object have to be static?
在许多其他问题中,每个人都说对象必须是readonly
。我没有找到原因 - 即使在MSDN或JavaDoc中也没有。
由于我经常使用这种结构,有人可以向我解释为什么要使用readonly
?
谢谢!
答案 0 :(得分:53)
如果我想确定它将被锁定在我的所有线程中 应用程序:
如果锁定对象锁定对静态的访问权限,则该锁定对象必须是静态的 否则它必须是实例,因为不需要锁定一个类实例的状态,并阻止其他线程同时使用另一个类实例。
每个人都说对象必须是“只读”我没有找到 原因
嗯,它不是必须。这只是一种最佳做法,可以帮助您避免错误。
考虑以下代码:
class MyClass
{
private object myLock = new object();
private int state;
public void Method1()
{
lock (myLock)
{
state = // ...
}
}
public void Method2()
{
myLock = new object();
lock (myLock)
{
state = // ...
}
}
}
这里Thread1可以通过Method1
获取锁定,但是要执行Method2
的Thread2将忽略此锁定,因为锁定对象已被更改=>国家可能已被腐败。
答案 1 :(得分:17)
它不必是只读的,但这是一个很好的做法,因为它可以避免意外更换它,这可能导致一些难以追踪的错误。
答案 2 :(得分:11)
我想这意味着“引用锁定对象的变量应该只读”。
锁定变量引用的锁定对象,而不是变量本身。即具有
private object Locker = new object();
你锁定了那个新对象(),而不是Locker字段。然后,如果您使用对另一个对象的引用替换该字段的值,请说
Locker = new object();
并锁定它,你锁定两个不同的对象,这就失去了锁定的目的,因为你现在没有获得同步访问。
答案 3 :(得分:6)
理想情况下,对象应该是只读的,以便不能将其更改为指向另一个对象。如果您对一个对象进行了锁定,那么另一个线程会更改该对象,如果,然后另一个线程出现,并尝试对该对象进行锁定,则该对象将不相同,因此原始锁定将是无效。
这将是一个非常罕见的情况。但是如果你对对象有一个锁定,而另一个线程在那个对象上等待,如果锁定线程调用Monitor.Pulse,则等待的线程被唤醒,并且可以对该对象进行锁定。在被唤醒和获取锁定之间的那段时间内,另一个线程可以更改锁中引用的对象,因此等待的线程将锁定另一个对象。