在C#中锁定一个在lock块中重新分配的对象

5

我有一个类中的代码:

private static MyObject _locker = new MyObject();

...

lock (_locker)
{
     ...
     _locker = new MyObject();
     ...
}

它会保持对_locker的锁定吗?

3
这似乎不是明智的想法,为什么你要这么做呢? - Hans Olsson
你应该使用 readonly 关键字标记 _locker 对象。 - Steven
3个回答

8
不会。根据C#规范(我强调的是):

A lock statement of the form lock (x) ... where x is an expression of a reference-type, is precisely equivalent to

System.Threading.Monitor.Enter(x);
try {
  ...
}
finally {
  System.Threading.Monitor.Exit(x);
}

except that x is only evaluated once.

由于x未重新评估,所以锁将被释放。


lock 关键字是语法糖。如果您在 .NET Framework 1.1 中使用托管 C++ 进行编码,您将不得不按照 João 指定的方式进行锁定。 - Sudesh Sawant
非常准确,Joao。谢谢你。 - Theodore Zographos

2
不要这样做。考虑使用完全不同的对象来保存锁的状态,而不一定是您想在锁语句中保护的对象。我经常编写这样的代码(好吧,并不经常):
private static readonly object _locker = new object();
private static MyObject _object;
...

lock (_locker)
{
     ...
     _object = new MyObject();
     ...
}

这涉及到与您所看到的完全不同的程序流程。lock()在代码中定义了一个关键部分 - 您不能将其用作任何类型对象的通用线程安全机制(我认为您的意图是在代码中使用它来实现这种机制?)


并将 _locker 声明为 readonly,以防止意外重新分配。 - LukeH
很棒的想法。已做出相应修改。 - Dave Markle
我希望能够创建一个状态对象,而不会使事情变得复杂。 - Theodore Zographos

2
我认为当调用了lock方法时,它将保持在设置为_lockerMyObject实例上的锁,也就是说,它将保持在_locker的原始实例上的锁,而不是在新创建的MyObject实例上的锁。在下面的代码中,第一次调用lock时,锁将保持在MyObject("OriginalInstance")上。当第二次调用时,它将锁定MyObject("NewInstance")
private static MyObject _locker = new MyObject("OriginalInstance");

...

lock (_locker)
{
    ...
    _locker = new MyObject("NewInstance");
    ...
}

因此,下一个线程可能会进入关键部分而没有问题,因为新实例没有被锁定。
不过,像这样做通常被认为是不好的做法。请参见MSDN以获取有关如何使用lock的建议。

嗯...这确实是一个不好的做法。我需要找到方法来防止重新实例化的发生。 - Theodore Zographos
按照其他人在这里已经说明的,将变量声明为“只读”。 - gehho

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接