Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么锁对象必须是只读的?_C#_Multithreading - Fatal编程技术网

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