使用String参数加锁时,加锁的对象是什么?

What object is the lock on when a String parameter is used for locking?

我在其中一个回购协议中遇到过这样的代码。我检查了一下,它有效。 (只有一个线程进入同步块。)

public Void hello(String s) {

    synchronized (s) {

        i++;
        System.out.println(i);
    }

    return null;
}

我的问题是锁是在字符串 class 本身上获得的吗?如果是,是否意味着如果代码库中的其他地方存在这样的代码,它们都会等待获得对同一对象的锁定?从而增加不必要的延迟?

String 对象上的内部锁是获取的锁。但是锁定是否有效取决于字符串是否始终是同一实例。字符串池和实习会影响这一点。

很难确定是否会使用同一个实例只是不这样做的原因之一。

如果应用程序中的两个 类 使用相同的字符串实例,那么其中一个可以获得锁并将另一个关闭。所以你可以让概念上不相关的对象相互影响,争用同一个锁。

人们也会感到困惑,认为他们可以使用字符串值来表示某些东西,并让代码在同步块或方法中更改 s 的值。这将打破所有的锁定。锁在对象上,而不是在变量上。更改值意味着当前持有锁的线程现在拥有旧对象,但试图进入的线程正在尝试获取新对象的锁,线程可以获取新对象并在前一个线程完成之前开始执行同步代码.

它有时可能会偶然工作,但这是一个糟糕的主意。使用专用对象作为锁:

private final Object lock = new Object();