## Why is this an issue?

Double-checked locking can be used for lazy initialization of `volatile` fields, but only if field assignment is the last step in the `synchronized` block. Otherwise you run the risk of threads accessing a half-initialized object.

### Noncompliant code example

    public class MyClass {

      private volatile List<String> strings;

      public List<String> getStrings() {
        if (strings == null) {  // check#1
          synchronized(MyClass.class) {
            if (strings == null) {
              strings = new ArrayList<>();  // Noncompliant
              strings.add("Hello");  //When threadA gets here, threadB can skip the synchronized block because check#1 is false
              strings.add("World");
            }
          }
        }
        return strings;
      }
    }

### Compliant solution

    public class MyClass {

      private volatile List<String> strings;

      public List<String> getStrings() {
        if (strings == null) {  // check#1
          synchronized(MyClass.class) {
            if (strings == null) {
              List<String> tmpList = new ArrayList<>();
              tmpList.add("Hello");
              tmpList.add("World");
              strings = tmpList;
            }
          }
        }
        return strings;
      }
    }

## Resources

- CERT, LCK10-J. - Use a correct form of the double-checked locking idiom

### Related rules

- {rule:java:S2168} - Double-checked locking should not be used