Comment by Sohcahtoa82

2 days ago

> There's no way to create a class that prevents callers from reading the object before the constructor runs (in multi-threaded software, new first hands a reference to the caller, which can put it on the heap, then it calls the constructor)

Which is why the pattern of double-checked locking doesn't work.

https://en.wikipedia.org/wiki/Double-checked_locking

It's wrong. The caller doesn't get the reference until the constructor runs. Although it looks like two operations in bytecode, the only thing you can legally do with an uninitialised object reference is call its constructor.

  • In java, the caller gets the reference before the constructor runs. It's in the language spec. It's terrible. You can prove it yourself with something like:

       this.dangerous = new Lol();
    

    and then have Lol()'s constructor sleep for 10 sec then set done = true at the end of the contstructor. In another thread:

       while(!this.dangerous) { }
       assert(this.done) // will throw.
    

    I guess you could use double-checked locking as a class author by having every public method on your class do a if (!this.done) { throw; }, and make sure there are no public fields.

    That's pretty lame though.

    • That's a data race. The caller gets the reference after the constructor runs, but writes to non-final fields from the constructor might not be visible to other threads.