Re: Solving Lazy Initialization and double checked locking problem

From: Vinay Aggarwal (vinay_at_t-e-c-h-l-o-b-b-y.com)
Date: 11/29/03


Date: Fri, 28 Nov 2003 23:33:00 GMT


Hey Roger,

That was a nice catch. I missed that one.

Now lets follow this logic. The compiler can only reorder the statements
if it does not change anything for the currently executing thread.
So can we create a side effect?

What if I change the inner class to something as follows.

    static class HeavyObjectInitSync extends
HeavyObjectInit // line 9
    {
        public volatile int i=0;
        public HeavyObject getHeavyObject(LazyInit
lazyInit) // line 11
        {
            HeavyObject heavyObject =
getHeavyObjectInternal(lazyInit); // line 13
            if(i>0)
                lazyInit.heavyObjectInit =
heavyObjectInitStatic; // line 14
            return
heavyObject;
// line 15
        }

        private synchronized HeavyObject getHeavyObjectInternal(LazyInit
lazyInit) // line 18
        {
            if(lazyInit.heavyObject ==
null) // line 20
            {
                lazyInit.heavyObject = new
HeavyObject(); // line 22
            }
            i++;
            return
lazyInit.heavyObject;
// line 24
        }
    }

Now the compiler is bound to keep them in straight order. What do you
think?

Vinay Aggarwal
CTO Techlobby
vinay at t e c h l o b b y dot com
h t t p : / / w w w. t e c h l o b b y . c o m /

Roger Lindsjö wrote:
>
> On Fri, 28 Nov 2003 19:32:23 +0100, Vinay Aggarwal wrote:
>
> > I have been thinking about the lazy initialization and double checked
> > locking problem. This problem is explain in detail here
> > http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html I
> > am not fully convinced that this problem cannot be solved. I am going to
> > propose a solution here. For the sake of discussion I will post my
> > solution here. It is possible that the proposed solution does not work,
> > feedback and comments are welcome.
>
> Sorry, but I don't think it works.
>
> > Since the thread is exiting a
> > syncronized method and the variable is volatile, the HeavyObject will be
> > fully initialized before the thread releases the lock. Now the lucky
> > thread will switch the implementation of heavyObjectInit to a non
> > syncronized initializer (line 14). Any threads reaching line 39 after
> > this will call the non syncronized version of getHeavyObject() at line
> > 31. At the same time, all the threads blocked at line 18 will enter the
> > getHeavyObjectInternal() method one by one and return with the singleton
> > heavy object instance.
>
> Here I think it goes wrong. The JIT should be free to reassign the
> instructions as long as it does not change the execution of the current
> thread according to the specs. This would allow it to:
>
> lazyInit.heavyObjectInit = heavyObjectInitStatic; // line 14
>
> before line 13 since this does not change anything for the executing
> thread. However, now another thread can enter LazyInit.getHeavyObject()
> and get the non synchronized implementation with an uninitialized object
> before the first thread has had a chance to fully create the heavy
> object.
>
> So the second thread could return a null object or a not fully
> initialized object.
>
> BTW, comp.lang.java does not exist.
>
> //Roger Lindsjö



Relevant Pages

  • Re: OT: Requesting C advice
    ... some behind the scenes action of the compiler. ... In fact the memory could ... Proper initialization means that floats and doubles must be initialized to 0.0 and pointers must be initialized to the null pointer value, even if those bit patterns differ from all-bits-zero. ...
    (Fedora)
  • Re: I think C# is forcing us to write more (redundant) code
    ... static void F(out string s) ... >> compiler enforced). ... locals here and locals are stack allocated, ... I don't have a problem with this explicit initialization in the current ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: memory management in Ada: tedious without GC?
    ... I don't like the permission to reorder operands, ... May the compiler group A and C and initialize both them by zeroing memory? ... If the initialization order were fixed, that would be illegal to do. ... subprograms, not as a pragma Pure, but as a contract. ...
    (comp.lang.ada)
  • Re: pointer and storage
    ... But, as always, a compiler is free to issue any diagnostics it ... If the initialization is executed, it invokes undefined behavior. ... In old versions of the C language, before "const" was introduced, this ...
    (comp.lang.c)
  • Re: inhibit compiler warning C4624 for a class hierarchy
    ... The undefined behavior means that the behavior is decided by the compiler. ... could appear due to member destructors not being called, ... I guess I can make the two-step initialization ... Compiler behavior would be well defined by the standard. ...
    (microsoft.public.vc.language)