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

本文关键字:对象 代码 执行期 锁定 | 更新日期: 2023-09-27 18:18:20

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

线程#1

lock(myObj) { ... }

后面的代码我有myObj = new XYZObj();

,然后线程#2锁定它

lock(myObj) { ... }

如果对象引用改变了,这段代码是线程安全的吗?当对象引用发生变化时,第一个锁仍然有效吗?

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

锁作用于实例,而不是变量。
lock语句将保留它自己对实例的引用,因此它只会退出您输入的实例。

规格说明:

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

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

除了x只求值一次。

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

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

No。它们都将锁定不同的对象。

根据MSDN

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

这个代码是线程安全的吗

语句lock(myObj) { ... }是安全的,直到一个新的对象引用被分配给myObj变量。附加:另外,只有当线程之间共享的数据在一个对象的锁内使用非原子变化时,只有在在同一个对象的锁内使用非原子变化时才安全。

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

如您所见,这种行为完全被破坏了。这是假设性的问题还是你真的这么做了?