当使用String参数进行锁定时,锁定在哪个对象上?



我在一个repos中遇到了这样的代码。我检查过了,还能用。(只有一个线程进入同步块)

public Void hello(String s) {
synchronized (s) {
i++;
System.out.println(i);
}
return null;
}

我的问题是在String类本身上获得的锁?如果是,这是否意味着如果这样的代码存在于代码库的其他地方,它们都将等待获得同一对象的锁?从而增加了不必要的延迟?

String对象上的固有锁是被获取的锁。但是锁是否有效取决于字符串是否总是相同的实例。字符串池和实习将影响这一点。

很难确定是否会使用相同的实例,这是不这样做的唯一原因。

如果应用程序中的两个类使用相同的字符串实例,则其中一个类可以获得锁并将另一个类拒之门外。因此,可以让概念上不相关的对象相互影响,争用同一个锁。

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

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

private final Object lock = new Object(); 

最新更新