Uploaded image for project: 'Rules Repository'
  1. Rules Repository
  2. RSPEC-2168

Double-checked locking should not be used

    XMLWordPrintable

    Details

    • Message:
      Remove this dangerous instance of double-checked locking.
    • Default Severity:
      Blocker
    • Impact:
      High
    • Likelihood:
      High
    • Default Quality Profiles:
      Sonar way
    • Covered Languages:
      Java
    • Remediation Function:
      Constant/Issue
    • Constant Cost:
      20min
    • Analysis Scope:
      Main Sources, Test Sources
    • Implementation details:
    • CERT:
      LCK10-J.
    • CWE:
      CWE-609
    • FindBugs:
      DC_DOUBLECHECK
    • PMD:
      DoubleCheckedLocking

      Description

      Double-checked locking is the practice of checking a lazy-initialized object's state both before and after a synchronized block is entered to determine whether or not to initialize the object.

      It does not work reliably in a platform-independent manner without additional synchronization for mutable instances of anything other than float or int. Using double-checked locking for the lazy initialization of any other type of primitive or mutable object risks a second thread using an uninitialized or partially initialized member while the first thread is still creating it, and crashing the program.

      There are multiple ways to fix this. The simplest one is to simply not use double checked locking at all, and synchronize the whole method instead. With early versions of the JVM, synchronizing the whole method was generally advised against for performance reasons. But synchronized performance has improved a lot in newer JVMs, so this is now a preferred solution. If you prefer to avoid using synchronized altogether, you can use an inner static class to hold the reference instead. Inner static classes are guaranteed to load lazily.

      Noncompliant Code Example

      @NotThreadSafe
      public class DoubleCheckedLocking {
          private static Resource resource;
      
          public static Resource getInstance() {
              if (resource == null) {
                  synchronized (DoubleCheckedLocking.class) {
                      if (resource == null)
                          resource = new Resource();
                  }
              }
              return resource;
          }
      
          static class Resource {
      
          }
      }
      

      Compliant Solution

      @ThreadSafe
      public class SafeLazyInitialization {
          private static Resource resource;
      
          public static synchronized Resource getInstance() {
              if (resource == null)
                  resource = new Resource();
              return resource;
          }
      
          static class Resource {
          }
      }
      

      With inner static holder:

      @ThreadSafe
      public class ResourceFactory {
          private static class ResourceHolder {
              public static Resource resource = new Resource(); // This will be lazily initialised
          }
      
          public static Resource getResource() {
              return ResourceFactory.ResourceHolder.resource;
          }
      
          static class Resource {
          }
      }
      

      Using "volatile":

      class ResourceFactory {
        private volatile Resource resource;
      
        public Resource getResource() {
          Resource localResource = resource;
          if (localResource == null) {
            synchronized (this) {
              localResource = resource;
              if (localResource == null) {
                resource = localResource = new Resource();
              }
            }
          }
          return localResource;
        }
      
        static class Resource {
        }
      }
      

      See

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              Unassigned Unassigned
              Reporter:
              ann.campbell.2 Ann Campbell
              Votes:
              1 Vote for this issue
              Watchers:
              3 Start watching this issue

                Dates

                Created:
                Updated: