有一个专门的锁对象有用吗?

Is it useful to have a dedicated object for a lock?

我正在清理遗留 java 代码,我发现了以下结构:

final class QuiteComplexClass {
    private Object lock = new Object();

    void aMethod() {
        ...
        synchronized(lock) {
              ....
        }
    }
}

这里需要加锁的特殊对象吗?我使用简单 synchronized (this) 时有什么区别?

我认为当 class 公开可见并且有人可能错误地在 class 实例上调用 synchronized 时它可能会有用。但是这个 class 是包私有的,所以没有外部代码可以做到这一点。

不,没有必要。使用锁定对象是一种旨在避免锁定实例的模式。这是否有价值通常是一个见仁见智的问题。

不同之处在于,如果您将 this 用作锁或将方法标记为 synchronized,那么另一段代码可能会意外(或故意)将您的 QuiteComplexClass 对象用作锁.它可能会导致您的代码无法正常工作。如果其他一些开发人员决定编写如下代码,那么您的代码将无法在持有锁时调用 qcc 实例上的 synchronized 方法。

synchronized(qcc) { // assuming qcc is an instance of QuiteComplexClass
   while (true); // or any other time consuming operation
}

Is the special object for locking necessary here? What is difference when I used simple synchronized (this)?

简短回答:不,没有必要,但除了添加 final 我认为删除它几乎没有任何好处。

我倾向于使用锁定对象,因为与 this 上的锁定相比,它们为我提供了更细粒度的锁定。例如,如果您要保护多个集合免受竞争条件的影响,您的 class 中可能有几个不同的锁对象。可以肯定的一件事是,您应该始终确保将锁定字段设置为 final.

private final Object lock = new Object();

这就是说,如果 class 很简单,并且您想确保人们知道哪些方法是 synchronized,那么在方法上使用关键字也是非常合适的。正如您提到的,这是一个内部 class,但即便如此,在外部 class 上工作的开发人员可能想了解同步点。