Ваша проблема в том, что блокировка Нефинал ссылка на переменную имеет бесполезную семантику .
Каждый раз, когда вы видите, что что-то делает synchronized(var);
, а var
является экземпляром или статической переменной и не помечается final
, это ошибка, потому что все может прийти и сделать var = new Thing();
и теперь есть как минимум 2 потока, которые могут работать с этим блоком одновременно, это логическая ошибка без исключений.Каждый контролер стиля Java lint помечает это как критическую ошибку, просто потому, что компилятор не улавливает это, не означает, что он в любом случае полезен.
В этом случае вы раскрываете эту бесполезную семантикуизменение значения неизменяемого Integer
класса.
Ваша Integer
переменная size
не является окончательной и равна Immutable
, что означает, что каждый раз, когда вы ее изменяете, вы должны изменить ссылку на новый объект, который представляет новое значение, и каждый поток получит новые и разные ссылки для привязки.Таким образом, без блокировки .
Используйте private static final AtomicInteger size = new AtomicInteger();
И тогда вы можете synchronize(size);
, поскольку size
теперь final
, вы можете изменить его на месте иполучить предполагаемую и правильную семантику.
или вы можете synchronize(some_other_final_reference);
и использовать обычный int
, пока эта ссылка, на которую синхронизируется, равна final
и может находиться в области действия любого потока, который долженприобрести ручку к нему, он будет работать.
Лично я бы использовал AtomicInteger
, так как он более сплоченный, вы фиксируете то, что вы не хотите менять, с помощью какого-либо другого потока, самодокументирования и ясных намерений.