1

Lets look at classical double check

class Foo {
    private volatile Foo singleton = null;
    public Foo getFooSingleton() {
        if (singleton == null) {
            synchronized(this) {           
                if (singleton == null)
                    singleton = new Foo();
            }
        }
        return singleton;
    }
}

Volatile modifire guaranties that value of "singleton" variable will be seen correctly in all threads. But really do I need this in current example? I think no. So - that's how I see this program runs in the worst way - when changes made by one thread are not seen by other.

  1. thread one enteres synchronized section and creates singleton
  2. thread two enteres synchronized, synchronize its current stack values (now he sees singleton != null), makes second check and exits synchronized section.

So. Everything works even without volatile declaration, and even better =)

user293756
  • 169
  • 1
  • 7
  • my guess is that you could be right if `singleton` is never set to `null` again. – svrist Mar 26 '11 at 19:15
  • I think you are missing that the Java Memory Model is not Sequentially Consistent. That is threads can see field read and writes in different orders (if not correctly synchronised). – Tom Hawtin - tackline Mar 26 '11 at 19:18
  • MMM, So you mean there is no Sequentially Consistents in synchronized block? – user293756 Mar 26 '11 at 19:42
  • No, you don't need volatile as your "singleton" doesn't have any state that needs to be safely published. As your object has no state, you don't need a singleton either. As your object has no methods, you actually don't need a class here. In fact the entire question is pointless. – Jed Wesley-Smith Mar 28 '11 at 02:57
  • related question: http://stackoverflow.com/questions/7855700/why-is-volatile-used-in-this-example-of-double-checked-locking – Robert Feb 12 '15 at 09:27

2 Answers2

5

Yes, volatile is needed here.

The point is that without memory barrier between creation of Foo (which includes creation of the object and execution of its constructor) and storing a reference to it in the singleton field other threads can observe these actions happening in arbitrary order. In particular, during the first check thread 2 can observe a reference pointing to the partically constructed object. Note that synchronized block can't help here, since thread 2 sees singleton != null and doesn't enter it at all.

Use of volatile ensures placing of the appropriate memory barrier (since Java 5; in previous versions double check idiom couldn't be implemented at all).

axtavt
  • 239,438
  • 41
  • 511
  • 482
  • MMM, As I Remember for se 6 specs says that constructor is guaranty to finish before link to object is passed(except unordinary, hand made, reference escape from constructor) – user293756 Mar 26 '11 at 20:12
  • No. "Just before a reference to the newly created object is returned as the result, the indicated constructor is processed " - for all objects - look reference to specs – user293756 Mar 26 '11 at 21:34
  • http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.5 – user293756 Mar 26 '11 at 21:35
  • @user293756: It's single-threaded semantics. Multithreaded semantics are defined in http://java.sun.com/docs/books/jls/third_edition/html/memory.html, and it doesn't provide any special guarantees about consturctors except for `final` fields. – axtavt Mar 27 '11 at 08:21
  • No. Theres only final semantica discussed. Theres guaranties provided for any constructor to be finished befor object is referenced – user293756 Mar 27 '11 at 09:53
  • http://www.cs.umd.edu/~pugh/java/memoryModel/jsr133.pdf – user293756 Mar 27 '11 at 09:54
  • MMM... Yes. I mean I think if ther is no any direct information about constructors of non-final fields - it might be not threadsafe =) – user293756 Mar 27 '11 at 10:06
2

The problem with DCL in Java is not the cost of extra synchronization. The real problem is that without volatile modifier (and before Java 5) your threads can see improperly constructed singleton object.

Just to be clear. Write to the singleton reference and writes to singleton's fields being sequential in singlethreaded program may be out of order in multithreaded.