锁定可变对象-为什么被视为一种不良实践?

11

请看这个答案。它说:

六个最糟糕的例子;

...

在可变字段上锁定。例如 synchronized(object) { object = ...; }

在可变字段上锁定有什么问题?如果object声明为final,但它不是一个不可变类呢?


2
我认为你把可变字段和不可变类(只包含不可变字段的类)混淆了。 - Kirk Woll
3个回答

16

这是一个不好的想法,因为如果另一个线程在关键部分更改了引用,那么线程将不再看到相同的引用,因此它们将不会同步在同一对象上,从而运行不受控制。 例如:

 synchronized(lock1) {
     lock1 = new Object();
     sharedVariable++;
 }

假设有2个线程试图进入此关键部分。线程1进入并等待线程2。线程1进入,重新分配lock1并继续执行。现在线程2看到的锁与线程1获取的不同,也是空闲的,因此它也可以进入关键部分。乐趣开始!

如果该对象是final,则无法将引用重新分配给另一个对象,因此上述问题不再适用。


6

这里“可变”不是正确的词语。锁定可变对象即有状态的对象是可以的,但是在锁定字段、更改它并期望另一个线程锁定同一对象时就是错误的。


1

我认为锁定可变对象本身并不是一件坏事。只是很难做到正确。还有其他的并发处理模型,比如演员模型。我建议你去了解一下 Akka,它可以从 Java 和 Scala 两种语言使用,并且是一个非常稳定的实现。


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