Синхронизация по локальной переменной

Я заметил странную конструкцию в ConcurrentHashMap "s compute а также computeIfAbsent методы:

Node<K,V> r = new ReservationNode<K,V>();
synchronized (r) {
  //...
}

Какой смысл синхронизировать локальный объект, если учесть, что JIT, скорее всего, будет рассматривать его как запрет?

1 ответ

Решение

Сразу после того, как код получил монитор объекта, ссылка на объект сохраняется в tab который является глобально видимым массивом узлов, которые составляют содержимое ConcurrentHashMap:

Node<K,V> r = new ReservationNode<K,V>();
synchronized (r) {
    if (casTabAt(tab, i, null, r)) {

Прямо в этот момент другие потоки, выполняющие другие методы модификации на том же ConcurrentHashMap может встретиться с этим неполным узлом при обходе глобального массива, другими словами, Node ссылка сбежала.

В то время как в точке, где ReservationNode был создан, нет возможности для конфликта на вновь созданном объекте, в других методах, которые синхронизируются на Nodeнайден в массиве, может быть конфликт именно Node,

Это как "приоритетная синхронизация". Создатель выполняет синхронизацию в точке, где ссылка еще не была экранирована, поэтому он гарантированно будет успешным, в то время как в точке, где ссылка выходит, все другие потоки должны будут ждать в маловероятном (но все еще возможном) событии, к которому они обращаются именно это Node,

Другие вопросы по тегам