C# 为什么锁对象必须是只读的?
实现锁时,我曾在类中创建一个私有对象:C# 为什么锁对象必须是只读的?,c#,multithreading,C#,Multithreading,实现锁时,我曾在类中创建一个私有对象: private object Locker = new object(); 如果我想确保它被锁定在创建我的类的线程中: private object Locker = new object(); 如果我想确保应用程序中的所有线程都将被锁定: private static object Locker = new object(); 但在这里: 在许多其他问题中,每个人都说对象必须是只读的。我还没有找到原因——甚至在MSDN或JavaDoc中也没有 由
private object Locker = new object();
如果我想确保它被锁定在创建我的类的线程中:
private object Locker = new object();
如果我想确保应用程序中的所有线程都将被锁定:
private static object Locker = new object();
但在这里:
在许多其他问题中,每个人都说对象必须是只读的
。我还没有找到原因——甚至在MSDN或JavaDoc中也没有
由于我经常使用这种结构,有人能给我解释一下为什么我要使用只读
谢谢 它不必是只读的,但这是一个很好的实践,因为它可以避免您意外地替换它,这可能会导致一些难以跟踪的错误。理想情况下,对象应该是只读的,以便它不能更改为指向另一个对象。如果你锁定了一个对象,那么另一个线程会改变这个对象,如果,那么另一个线程会出现,并试图锁定这个对象,那么这个对象就不一样了,所以原来的锁会失效
这将是一个非常罕见的案例。但是,如果对象上有一个锁,另一个线程正在等待该对象,如果锁定线程调用Monitor.Pulse,等待的线程将被唤醒,并可以获得该对象上的锁。在被唤醒和获取锁之间的这段时间内,另一个线程可能会更改锁中引用的对象,因此等待的线程将在另一个对象上获取锁
如果我想确保它将被锁定在我的
应用程序:
private static object Locker = new object();
锁定对象必须是静态的,如果它将访问锁定为静态。
否则它必须是实例,因为不需要锁定一个类实例的状态,并且防止其他线程同时处理另一个类实例
每个人都说对象必须是“只读”的我没有找到
理由
嗯,不一定是这样。这只是一个最佳实践,可以帮助您避免错误
考虑以下代码:
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将忽略此锁,因为lock对象已更改=>状态可能已损坏。我猜这意味着“引用锁对象的变量应为只读”
锁定变量引用的锁定对象,而不是变量本身。即有
private object Locker = new object();
您锁定的是那个新对象(),而不是Locker字段。然后,如果将字段的值替换为对另一个对象的引用,例如
Locker = new object();
然后锁定它,您正在锁定两个不同的对象,这就违背了锁定的目的,因为您现在无法获得同步访问。不需要将Locker(静态或非静态)设为只读;但是如果Locker是只读的,代码看起来更准确:我们强调Locker实例不能更改,我看到了,非常感谢您的解释。可能是因为我习惯于根据要访问的资源(或方法)创建不同的锁,所以我从未遇到过这种情况,但现在我明白,无论如何,只读是一种良好的做法,不会损害我的代码。@Dennis,只读是有意义的。但在锁中不需要静态。假设我不会在仅使用static时标记readonly,行为将与私有对象myLock=new object()相同@Sudhir.net:恐怕我不明白你的意思<当myLock
保护静态(即静态字段)时,需要code>static
。如果在本例中省略了static
,则每个类型实例都将有自己的myLock
,这毫无意义。谢谢Dennis。myLock vairable对于任何特定类都是私有的。它不会在其他类中共享。如果我使用readonly,那么没有人可以创建对象。所以状态不会改变,那么在一个类中myLock的状态也不会改变。然后我的问题是,myLock需要什么样的静态?@Sudhir.net:如果lock(myLock){…}
中的代码访问静态字段,那么您需要Static
,因为静态字段在类实例之间共享。如果lock
中的代码仅适用于实例字段(即字段,声明时没有static
关键字),则不要将static
用于myLock
。