2

hi,i have a problem on double check lock in singleton pattern。 in follow code :

private volatile   static DoubleCheckSingleton instance;

private DoubleCheckSingleton() {}


public static DoubleCheckSingleton getInstance(){

    if(instance==null){ //first

        synchronized (DoubleCheckSingleton.class){

            if(instance==null){  // second
                instance=new DoubleCheckSingleton();
            }

        }

    }

    return instance;

}

Suppose there are now two threads, A and B respectively. Afterwards they execute simultaneously. According to happens-before definition, after one thread releases the lock, another thread acquires the lock, then the latter can see the previous change.

If so, I don't think the volatile keyword is needed, so why should we use the volatile keyword here? Which friend can explain it? Thank you for your answer

Qin Dong Liang
  • 415
  • 3
  • 12
  • I don't understand what you mean, can you explain it in detail? – Qin Dong Liang Jul 04 '18 at 16:31
  • 1
    is this just an academic question? Otherwise you should have a look at the [initialization-on-demand holder idiom](https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom) – dpr Jul 04 '18 at 16:35
  • 1
    Probably use the `static-holder-class`-Pattern mentioned [here](https://stackoverflow.com/questions/15019306/regarding-static-holder-singleton-pattern) – Lino Jul 04 '18 at 16:37
  • My question is why you need the volatile keyword since you have the happens-before rule.Does happens-before not take effect? @all – Qin Dong Liang Jul 04 '18 at 16:40
  • happens-before takes effect on the synchronized keyword, which is after you evaluated the if. This if doesn't define any happens-before property if the variable isn't volatile, and therefore the effects are arbitrary. – kumesana Jul 04 '18 at 16:42
  • According to happens-before definition, after one thread releases the lock, another thread acquires the lock, then the latter can see the previous change。Since you can see the changes, why do you need the volatile keyword? @kumesana – Qin Dong Liang Jul 04 '18 at 16:50
  • 1
    The problem without the volatile keyword is that you can see the changes while they are happening. There is no happens-before rules that says otherwise. So a thread can arrive there and see a non-null instance while it is being built and absolutely not ready to use. Yet, this thread will not get into the if and it will start using the instance that's not ready for use. – kumesana Jul 04 '18 at 16:51
  • I still don't understand what you mean. Here is the sychronized keyword. In the second null check of the above code, if there is the happends-before rule, after thread A releases the lock, thread B can see that the instance is not null, then , I really don't understand why the singleton also needs to use volatile to ensure visibility. @kumesana – Qin Dong Liang Jul 04 '18 at 17:00
  • I'm telling you that the problem is not to ensure that thread B can see a fully built object. The problem is to ensure that thead B cannot see a non-null object that's not fully built. If it does, then the the first null check tells B to not care about synchronization, and therefore it won't matter that you attempted to have synchronization. – kumesana Jul 04 '18 at 17:03
  • Is the above code correct if there is no volatile keyword? @kumesana – Qin Dong Liang Jul 04 '18 at 17:11
  • @QinDongLiang if the first condition is false, there is no synchronized, no memory barrier and the thread can see an object which hasn't been initialised properly. – Peter Lawrey Jul 04 '18 at 17:12
  • without volatile, it's not correct. – Peter Lawrey Jul 04 '18 at 17:13
  • Like I said, it will provide callers of the getInstance() method with an instance of DoubleCheckSingleton that's currently being worked on by a thread that's building it.That is definitely not correct. Such an instance is in an invalid state and using it will break all expectations. – kumesana Jul 04 '18 at 17:14
  • According to the definition of happens-before ,The synchronized code block ensures that the next thread that gets the lock can see the latest changes, which is the same as the volatile keyword. If the same, the volatile keyword is not needed here. @kumesana – Qin Dong Liang Jul 04 '18 at 17:27
  • You're still failing to consider the next thread that doesn't get the lock, because it is not trying to get the lock. – kumesana Jul 04 '18 at 17:53
  • @kumesana good morninig. Let us continue the discussion。 Why won't the next thread get the lock? – Qin Dong Liang Jul 05 '18 at 01:41
  • Hi. The next thread reaches the first null check and sees a non-null variable. Because of that it doesn't get into the if, and therefore isn't involved with the synchronized block. Without a synchronized block, there is no lock to try and get. Because it doesn't have a lock to try and get, it won't get that lock that doesn't exist. – kumesana Jul 05 '18 at 08:01
  • @kumesana The next thread, if there no happends-before relationship, it can't see changes, so it can only see null values . What do you think? by the way Which country are you in . Nice to meet you . – Qin Dong Liang Jul 05 '18 at 08:29
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/174394/discussion-between-kumesana-and-qin-dong-liang). – kumesana Jul 05 '18 at 08:51
  • hi @kumesana what are you doing ? i have a new problem which need your help – Qin Dong Liang Jul 06 '18 at 12:06
  • @kumesana in java sychionized keyword can prevent reordering of code ? – Qin Dong Liang Jul 06 '18 at 12:09
  • @QinDongLiang of course, as part of ensuring happens-before relationships. – kumesana Jul 06 '18 at 13:27

0 Answers0