看到这个answer。它说:锁定可变对象 - 为什么它被认为是不好的做法?
六真是不好的例子;
...
锁定在可变字段上。例如synchronized(object){object = ...; }
锁定可变字段有什么问题?如果object
被宣布为final
但是不是不可变的类呢?
看到这个answer。它说:锁定可变对象 - 为什么它被认为是不好的做法?
六真是不好的例子;
...
锁定在可变字段上。例如synchronized(object){object = ...; }
锁定可变字段有什么问题?如果object
被宣布为final
但是不是不可变的类呢?
这是一个坏主意,因为如果另一个线程更改关键部分中的引用,线程将不再看到相同的引用,因此它们将不会在同一个对象上同步,从而运行不受控制。例如:
synchronized(lock1) {
lock1 = new Object();
sharedVariable++;
}
假设2个线程试图进入这个关键部分。线程1进入并且线程2等待。线程1进入,重新分配lock1
并继续。现在线程2看到的线程与线程1获取的不同,它也是免费的,所以它也可以进入临界区。乐趣随之而来!
如果对象是final
,则不能将引用重新分配给其他对象,因此上述问题不再适用。
“可变”在这里不是正确的词。可以锁定可变对象,即具有状态的对象。什么是错误的是锁定一个字段,改变它,并期望另一个线程锁定在同一个对象上。
我不认为锁定可变对象本身是不好的。这很难让它正确。还有其他模型用于并发处理,如演员。我建议你看看Akka,它可以从Java和Scala中使用,并且是一个非常稳定的实现。
我认为你让可变字段与不可变类(只包含不可变字段的类)混淆。 – 2012-03-08 17:52:44