Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8320842

Double-Check-Locking (DCL) is ineffective

XMLWordPrintable

    • x86_64
    • windows

      ADDITIONAL SYSTEM INFORMATION :
      OS:
      windows11, version: 22H2

      JDK:
      java -version:
      java version "17.0.6" 2023-01-17 LTS
      Java(TM) SE Runtime Environment (build 17.0.6+9-LTS-190)
      Java HotSpot(TM) 64-Bit Server VM (build 17.0.6+9-LTS-190, mixed mode, sharing)

      A DESCRIPTION OF THE PROBLEM :
      I used the double-check-locking to create a singleton object, but it was failed because I get the null instance sometimes.

      I am thinking that if it works well, the null instance should not be appeared.
      So may there be something wrong in JDK (especially the synchronized or volatile has some bugs) or something wrong in my example below.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the below class "LazyManTest" again and again.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The "LazyMan instance" is only one instance and should not be null.
      ACTUAL -
      Sometimes the "LazyMan instance" will contain a null object which is so strange.

      ---------- BEGIN SOURCE ----------
      1.The first class is: -----------------------------------

      public class LazyMan {

          private static volatile LazyMan INSTANCE;
          private LazyMan() {}

          public static LazyMan getInstance() {
              if (INSTANCE == null) {
                  synchronized (LazyMan.class) {
                      if (INSTANCE == null) {
                          INSTANCE = new LazyMan();
                      }
                  }
              }
              return INSTANCE;
          }

      }

      2.The second test class is:---------------------------------------

      import java.util.*;
      import java.util.concurrent.ExecutorService;
      import java.util.concurrent.Executors;
      import java.util.concurrent.TimeUnit;

      public class LazyManTest {

          public static void main(String[] args) throws Exception {
              ExecutorService executorService = Executors.newFixedThreadPool(50);
              // We can ignore the thread safety of ArrayList because it doesn't affect the singleton test.
              List<LazyMan> list = new ArrayList<>();
              for (int i = 0; i < 10000; i++) {
                  executorService.submit(() -> {
                      LazyMan lazyMan = LazyMan.getInstance();
                      list.add(lazyMan);
                  });
              }
              TimeUnit.SECONDS.sleep(5L);
              Set<LazyMan> set = new HashSet<>(list);
              System.out.println("LazyMan instance -------> ");
              System.out.println(set);
              executorService.shutdown();
          }
      }

      ---------- END SOURCE ----------

      FREQUENCY : occasionally


            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: