## Why is this an issue?

In Java, value-based classes are those for which instances are final and immutable, like `String`, `Integer` and so on, and their identity relies on their value and not their reference. When a variable of one of these types is instantiated, the JVM caches its value, and the variable is just a reference to that value. For example, multiple `String` variables with the same value "Hello world!" will refer to the same cached string literal in memory.

The `synchronized` keyword tells the JVM to only allow the execution of the code contained in the following block to one `Thread` at a time. This mechanism relies on the identity of the object that is being synchronized between threads, to prevent that if object X is locked, it will still be possible to lock another object Y.

It means that the JVM will fail to correctly synchronize threads on instances of the aforementioned value-based classes, for instance:

    // These variables "a" and "b" will effectively reference the same object in memory
    Integer a = 0;
    Integer b = 0;

    // This means that in the following code, the JVM could try to lock and execute
    // on the variable "a" because "b" was notified to be released, as the two Integer variables
    // are the same object to the JVM
    void syncMethod(int x) {
        synchronized (a) {
            if (a == x) {
            // ... do something here
            }
        }
        synchronized (b) {
            if (b == x) {
            // ... do something else
            }
        }
    }

This behavior can cause unrelated threads to deadlock with unclear stacktraces.

Within the JDK, types which should not be used for synchronization include:

- `String` literals
- Primitive wrapper classes in `java.lang` (such as `Boolean` with `Boolean.FALSE` and `Boolean.TRUE`)
- The class `java.lang.Runtime.Version`
- The `Optional*` classes in `java.util`: `Optional`, `OptionalInt`, `OptionalLong`, and `OptionalDouble`
- Various classes in the `java.time` API: `Instant`, `LocalDate`, `LocalTime`, `LocalDateTime`, `ZonedDateTime`, `ZoneId`, `OffsetTime`, `OffsetDateTime`, `ZoneOffset`, `Duration`, `Period`, `Year`, `YearMonth`, and `MonthDay`
- Various classes in the `java.time.chrono` API: `MinguoDate`, `HijrahDate`, `JapaneseDate`, and `ThaiBuddhistDate`
- The interface `java.lang.ProcessHandle` and its implementation classes
- The implementation classes of the collection factories in `java.util`: `List.of`, `List.copyOf`, `Set.of`, `Set.copyOf`, `Map.of`, `Map.copyOf`, `Map.ofEntries`, and `Map.entry`.

## How to fix it

Replace instances of value-based classes with a new object instance to synchronize on.

### Code examples

#### Noncompliant code example

    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
          ...
      }

#### Compliant solution

    private static final Object lock1 = new Object();
    private static final Integer iLock = new Integer(42);
    private static final String sLock = new String("A brand new string in memory!");
    private static final List<String> listLock = new ArrayList<>();

    public void doSomething() {

      synchronized(lock1) { // Compliant
          ...
      }
      synchronized(iLock) { // Compliant
          ...
      }
      synchronized(sLock) { // Compliant
          ...
      }
      synchronized(listLock) { // Compliant
          ...
      }

## Resources

- CERT - Do not synchronize on objects that may be reused
- OpenJDK - JEP 390: Warnings for Value-Based Classes
- Java Documentation - Value-based Classes