Instances of value-based classes, which are pooled and potentially reused, should not be used for synchronization. If they are, it can cause unrelated threads to deadlock with unhelpful stacktraces.
Within the JDK, types which should not be used for synchronization include:
String
literals java.lang
(such as Boolean
with Boolean.FALSE
and
Boolean.TRUE
) java.lang.Runtime.Version
Optional*
classes in java.util
: Optional
, OptionalInt
, OptionalLong
, and
OptionalDouble
java.time
API: Instant
, LocalDate
, LocalTime
,
LocalDateTime
, ZonedDateTime
, ZoneId
, OffsetTime
, OffsetDateTime
,
ZoneOffset
, Duration
, Period
, Year
, YearMonth
, and MonthDay
java.time.chrono
API: MinguoDate
, HijrahDate
, JapaneseDate
, and
ThaiBuddhistDate
java.lang.ProcessHandle
and its implementation classes java.util
: List.of
, List.copyOf
,
Set.of
, Set.copyOf
, Map.of
, Map.copyOf
, Map.ofEntries
, and Map.entry
.
Replace instances of value-based classes with a new object instance to synchronize on.
private static final Boolean bLock = Boolean.FALSE; private static final Integer iLock = Integer.valueOf(0); private static final String sLock = "LOCK"; private static final List<String> listLock = List.of("a", "b", "c", "d"); public void doSomething() { synchronized(bLock) { // Noncompliant ... } synchronized(iLock) { // Noncompliant ... } synchronized(sLock) { // Noncompliant ... } synchronized(listLock) { // Noncompliant ... }
private static final Object lock1 = new Object(); private static final Object lock2 = new Object(); private static final Object lock3 = new Object(); private static final Object lock4 = new Object(); public void doSomething() { synchronized(lock1) { // Compliant ... } synchronized(lock2) { // Compliant ... } synchronized(lock3) { // Compliant ... } synchronized(lock4) { // Compliant ... }