Причина такого поведения в том, что конкатенация String, если оба операнда не являются выражениями констант времени компиляции, приводит к созданию нового экземпляра String. См. здесь на языке spe c:
Объект String создается заново (§12.5), если выражение не является константным выражением (§15.29).
Параметры метода не являются выражениями констант времени компиляции, так как метод может быть вызван с любым значением параметра.
И, поскольку текущий поток является единственным потоком, который имеет доступ к этому только что созданная строка, синхронизация с ней не имеет никакого эффекта.
Поскольку вы говорите, что не хотите знать альтернативы, я остановлюсь на этом.
Вы, кажется, не убеждены, несмотря на то, что я указал на соответствующую часть SPE c, что струны, на которых вы синхронизируете, разные. Попробуйте добавить эту строку прямо перед synchronized
:
System.out.println(System.identityHashCode(lock)); // Add this
synchronized (lock) {
// ...
. Это распечатает «идентификатор ha sh код» блокировки, который не совпадает с lock.hashCode()
, который основывается на значении строки. Это покажет, что synchronized
синхронизируется с разными значениями (если только вы исключительно повезло / не повезло, поскольку ha sh коллизии маловероятны, но возможны).