锁定在代码执行期间可能更改的对象

时间:2011-12-20 16:44:58

标签: c# multithreading

假设我有一个锁定对象引用的线程

线程#1

lock(myObj) { ... }

稍后在代码中我有myObj = new XYZObj();

然后线程#2锁定它

lock(myObj) { ... }

如果对象引用已更改,此代码是否是线程安全的?当对象引用发生更改时,第一个锁仍然有效吗?

3 个答案:

答案 0 :(得分:7)

锁定可以处理实例,而不是变量 lock语句将保留对实例的引用,以便它只退出您输入的实例。

spec说:

  

其中x是引用类型的表达式,精确等效   到

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

,但x只评估一次。

如果在两个锁之间重新分配变量,则会在两个不同的实例上获得两个有效锁。

但是,一般来说,你永远不应该这样做;这是一个微妙的错误和竞争条件的配方 您应该只锁定专用的只读锁定对象。

答案 1 :(得分:3)

没有。它们都会锁定不同的物体。

根据MSDN

  

最佳做法是定义要锁定的私有对象或私有对象   静态对象变量,用于保护所有实例共有的数据。

答案 2 :(得分:2)

  

此代码是否是线程安全的

语句lock(myObj) { ... }仅在将新对象引用分配给myObj变量之前才是安全的。 另外:此外,如果在对象的锁内部使用非原子变异的线程之间共享的任何数据在锁内部使用非原子变异,那么它是唯一安全的同一个对象。

因此,每次为myObj输入锁定时,实际引用的对象就是用于锁定的对象,而不是变量。如果更改变量以引用新对象,那么您可以有效地将不同的对象锁定在不同的锁中,这显然不是您想要的。但是,再次,当您下次返回第一个锁时,第一个和第二个锁定对象可能再次同步,因此它将再次安全。也许吧!

如您所见,这种行为完全被打破了。这是一个假设的问题,还是你真的这样做?