Exforsys
+ Reply to Thread
Page 1 of 2 12 LastLast
Results 1 to 10 of 20

Solving Lazy Initialization and double checked locking problem

This is a discussion on Solving Lazy Initialization and double checked locking problem within the Software Patterns forums, part of the Testing category; I have been thinking about the lazy initialization and double checked locking problem. This problem is explain in detail here ...

  1. #1
    Vinay Aggarwal Guest

    Solving Lazy Initialization and double checked locking problem


    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/mem...edLocking.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.

    Here is the original problem. We need to lazy initialize a non static
    variable to an instance of a heavy object in a thread safe way. (It is
    very easy to safely initialize a static variable). The most commonly
    used code is as follows:
    ---------------------------------------------------------------------------
    public class LazyInit
    {
    private HeavyObject heavyObject =
    null;

    public HeavyObject
    getHeavyObject()
    {
    if (heavyObject ==
    null)
    {
    synchronized(this)
    {
    if (heavyObject == null)
    {
    heavyObject = new HeavyObject();
    }
    }
    }
    return
    heavyObject;
    }
    }

    ---------------------------------------------------------------------------

    Unfortunately, this code is broken as described at
    http://www.cs.umd.edu/~pugh/java/mem...edLocking.html.
    The problem arises from the fact that the optimising compilers can
    reorder the constructor call and the assignment to the heavyObject
    variable.

    In my proposed solution, I am going to use polymorphism to appropriately
    syncronize the initialization and after its safe initialization, replace
    the implementation itself to be unsynchronized. Here is the code,
    detailed description follows.

    ---------------------------------------------------------------------------
    import java.util.*;

    public class
    LazyInit
    // line 3
    {
    private static HeavyObjectInit heavyObjectInitStatic = new
    HeavyObjectInit(); // line 5
    private HeavyObjectInit heavyObjectInit = new
    HeavyObjectInitSync(); // line 6
    private volatile HeavyObject heavyObject =
    null; // line 7

    static class HeavyObjectInitSync extends
    HeavyObjectInit // line 9
    {
    public HeavyObject getHeavyObject(LazyInit
    lazyInit) // line 11
    {
    HeavyObject heavyObject =
    getHeavyObjectInternal(lazyInit); // line 13
    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
    }
    return
    lazyInit.heavyObject;
    // line 24
    }

    }

    static class
    HeavyObjectInit
    // line 29
    {
    public HeavyObject getHeavyObject(LazyInit
    lazyInit) // line 31
    {
    return
    lazyInit.heavyObject;
    // line 33
    }
    }

    public HeavyObject
    getHeavyObject()
    // line 37
    {
    return
    heavyObjectInit.getHeavyObject(this);
    // line 39
    }
    }

    ---------------------------------------------------------------------------

    Explanation:
    Lets assume this code is executing in a multi threading environment. Now
    lets say a few threads enter LazyInit.getHeavyObject() at line 37
    simultaneously. These threads will reach
    heavyObjectInit.getHeavyObject() at line 39. Since heavyObjectInit is
    initialized to HeavyObjectInitSync (at line 6), these threads will enter
    getheavyObject() at line 11. At line 13, only one thread (lucky thread)
    will be able to enter the syncronized method getHeavyObjectInternal
    while rest of threads will be blocked at line 18. The lucky thread will
    initialize the heavy object and return it. 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.

    Thus initially a few threads will be synchronized till the lucky thread
    switches the initializer. At this time the system will switch to non
    syncronized implementation. Note that non syncronized implementation
    (line 33) does not even incur the cost of null check as compared to the
    original algorithm.

    There are some intricacies that I have tried to explain in Q&A form.


    Why is the instance of HeavyObjectInitSync nonstatic while instance of
    HeavyObjectInit static?
    If the HeavyObjectInitSync instance is made static, the syncronized
    method will syncronize on the single instance of the class. Since all
    instances of LazyInit will refer to single instance of
    HeavyObjectInitSync, the call will be mutually exclusive across ALL
    instances of LazyInit. Essentially if there are 1000 LazyInit objects
    each one wanting to initialize HeavyObjects, these objects will get
    initialized sequentially, thus slowing down the process. By making the
    instance non static, different instances of LazyInit can initialize the
    HeavyObject in parallel.
    The HeavyObjectInit instance is static because we dont need one instance
    of the HeavyObjectInit class with every instance of LazyInit. This
    eliminates unnecessary object creation.

    Why is HeavyObjectInitSync class static?
    This class can be static or non-static. It is a matter of personal
    choice. It should work both ways. I wanted to be consistent with
    HeavyObjectInit class.

    I have a code sample that shows how different threads will execute.
    Download it here http://24.167.121.42/LazyInit.java

    The output of this program demonstrates
    1. Different threads entering one instance of LazyInit get blocked till
    the HeavyObject is initialized.
    2. Different threads entering different instances of LazyInit can
    initialize the heavy object simultaneously.
    3. The HeaveyObject is initialized only once per instance of LazyInit.
    4. After the initialization is complete, any other threads entering that
    instance of LazyInit do not syncronize anymore.


    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 /



  2. #2
    =?iso885915?q?Roger_Lindsj=F6?= Guest

    Re: Solving Lazy Initialization and double checked locking problem

    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/mem...edLocking.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ö



  3. #3
    Vinay Aggarwal Guest

    Re: Solving Lazy Initialization and double checked locking problem


    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/mem...edLocking.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ö




  4. #4
    pete kirkham Guest

    Re: Solving Lazy Initialization and double checked locking problem

    DCL is not much of a problem in the real world. AFAIK no-one has ever
    given an example of a profiled application on a modern JVM where the
    additional overhead of a synchronized call makes enough of a difference
    to use complex DCL alternatives. Show me some code that
    does something useful and has at least a 10% improvement in speed in its
    critical path by making a faster synchronization mechanism for singletons.

    The common solutions to lazy creation are to use class/instance
    synchronization (singletons and per-instance resources):

    [static] HeavyObject heavyObject;
    public [static] synchronized getHeavyObject () {
    if (heavyObject==null) {
    heavyObject = new HeavyObject();
    }
    return heavyObject;
    }

    or the first-call synchronization implicit in class loading (singletons
    only):

    class HeavyObjectGuardian {
    static HeavyObject heavyObject = new HeavyObject();
    }

    public static getHeavyObject () {
    return HeavyObjectGuardian.heavyObject;
    }

    Edge cases exist where the singleton needs to be released, but your
    example doesn't help that in its current form - that would require safe
    setting of the heavyObjectInit field, and so you're back to square one
    synchronizing that.

    On a single or dual processor machine with a recent JVM, a synchronized
    method call is only very slightly slower than an non-synchronized call -
    DCL was an artifact to get round the slow synchronization in early JVMs.

    Speed was the only reason to use DCL in the first place. DCL compromised
    deterministic thread safety with probabalistic thread safety (there are
    no recorded examples of it failing, but it is theoretically possible) in
    order to gain a speed advantage by not using synchronization, as
    synchronization was costly at the time.

    Therefore alternatives to DCL must be deterministically thread safe (you
    can still use DCL if you only need probable safety - if a plane journey
    were as safe as a DCL access, then you could travel every day for a
    million years and never crash), and either faster or simpler than the
    two patterns above to be worthwhile. Those two examples are thread safe,
    so execution speed is the *only* criteria to judge a different thread
    safe pattern against them.

    Plot a graph showing how much faster your method is on single, dual and
    multiple processors architectures when compared to the two normal
    solutions above, and explain why the additional complexity is worth the
    effort in a typical application, where method invocation overhead is a
    very minor cost. Without profiling your pattern in a realistic
    sscenario, there is nothing to judge its merit, and the simplist
    solution wins.


    Pete




  5. #5
    Vinay Aggarwal Guest

    Re: Solving Lazy Initialization and double checked locking problem


    Hey Pete,

    I do agree with you on some points and disagree on others. You are
    correct that mostly this problem doesn't bother us in real world.
    Syncronizing the whole method usually is good enough. However I cannot
    say that every application in the world will be better off with
    syncronizing the get method. It may be true, it may not. I will
    let individual application authors decide what they want to use.
    I believe there are applications where reliability and responsiveness
    is much more important than solution complexity. For example
    stock trading applications or infrastructure pieces like EJB
    containers.

    My solution does seems complicated than DCL but well its the only
    deterministic alternative to method syncronization for instance based
    singletons. Individual application authors have to decide for
    themselves about how much do they stand to gain with different
    implementations. The performance can have huge variation depending on
    the application architecture. Hence any numbers I provide are
    probably not useful in real world.

    One of my motives of solving the problem was just to take a shot at
    a problem that experts say cannot be solved. Not only that, I also
    believe that this pattern can be used to solve other problems as
    well. For example, you mentioned that releasing the singletons is
    an issue for some cases. My solution can possibly be extended to
    solve such problems.

    This whole exercise could be just theoretical. Its out there
    in case somebody wants to use it. If there are efforts to change
    memory models and threading specifications to solve this problem,
    my solution probably interests somebody.

    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 /



    pete kirkham wrote:
    >
    > DCL is not much of a problem in the real world. AFAIK no-one has ever
    > given an example of a profiled application on a modern JVM where the
    > additional overhead of a synchronized call makes enough of a difference
    > to use complex DCL alternatives. Show me some code that
    > does something useful and has at least a 10% improvement in speed in its
    > critical path by making a faster synchronization mechanism for singletons.
    >
    > The common solutions to lazy creation are to use class/instance
    > synchronization (singletons and per-instance resources):
    >
    > [static] HeavyObject heavyObject;
    > public [static] synchronized getHeavyObject () {
    > if (heavyObject==null) {
    > heavyObject = new HeavyObject();
    > }
    > return heavyObject;
    > }
    >
    > or the first-call synchronization implicit in class loading (singletons
    > only):
    >
    > class HeavyObjectGuardian {
    > static HeavyObject heavyObject = new HeavyObject();
    > }
    >
    > public static getHeavyObject () {
    > return HeavyObjectGuardian.heavyObject;
    > }
    >
    > Edge cases exist where the singleton needs to be released, but your
    > example doesn't help that in its current form - that would require safe
    > setting of the heavyObjectInit field, and so you're back to square one
    > synchronizing that.
    >
    > On a single or dual processor machine with a recent JVM, a synchronized
    > method call is only very slightly slower than an non-synchronized call -
    > DCL was an artifact to get round the slow synchronization in early JVMs.
    >
    > Speed was the only reason to use DCL in the first place. DCL compromised
    > deterministic thread safety with probabalistic thread safety (there are
    > no recorded examples of it failing, but it is theoretically possible) in
    > order to gain a speed advantage by not using synchronization, as
    > synchronization was costly at the time.
    >
    > Therefore alternatives to DCL must be deterministically thread safe (you
    > can still use DCL if you only need probable safety - if a plane journey
    > were as safe as a DCL access, then you could travel every day for a
    > million years and never crash), and either faster or simpler than the
    > two patterns above to be worthwhile. Those two examples are thread safe,
    > so execution speed is the *only* criteria to judge a different thread
    > safe pattern against them.
    >
    > Plot a graph showing how much faster your method is on single, dual and
    > multiple processors architectures when compared to the two normal
    > solutions above, and explain why the additional complexity is worth the
    > effort in a typical application, where method invocation overhead is a
    > very minor cost. Without profiling your pattern in a realistic
    > sscenario, there is nothing to judge its merit, and the simplist
    > solution wins.
    >
    > Pete




  6. #6
    Vinay Aggarwal Guest

    Re: Solving Lazy Initialization and double checked locking problem


    Hey Pete,

    I do agree with you on some points and disagree on others. You are
    correct that mostly this problem doesn't bother us in real world.
    Syncronizing the whole method usually is good enough. However I cannot
    say that every application in the world will be better off with
    syncronizing the get method. It may be true, it may not. I will
    let individual application authors decide what they want to use.
    I believe there are applications where reliability and responsiveness
    is much more important than solution complexity. For example
    stock trading applications or infrastructure pieces like EJB
    containers.

    My solution does seems complicated than DCL but well its the only
    deterministic alternative to method syncronization for instance based
    singletons. Individual application authors have to decide for
    themselves about how much do they stand to gain with different
    implementations. The performance can have huge variation depending on
    the application architecture. Hence any numbers I provide are
    probably not useful in real world.

    One of my motives of solving the problem was just to take a shot at
    a problem that experts say cannot be solved. Not only that, I also
    believe that this pattern can be used to solve other problems as
    well. For example, you mentioned that releasing the singletons is
    an issue for some cases. My solution can possibly be extended to
    solve such problems.

    This whole exercise could be just theoretical. Its out there
    in case somebody wants to use it. If there are efforts to change
    memory models and threading specifications to solve this problem,
    my solution probably interests somebody.

    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 /



    pete kirkham wrote:
    >
    > DCL is not much of a problem in the real world. AFAIK no-one has ever
    > given an example of a profiled application on a modern JVM where the
    > additional overhead of a synchronized call makes enough of a difference
    > to use complex DCL alternatives. Show me some code that
    > does something useful and has at least a 10% improvement in speed in its
    > critical path by making a faster synchronization mechanism for singletons.
    >
    > The common solutions to lazy creation are to use class/instance
    > synchronization (singletons and per-instance resources):
    >
    > [static] HeavyObject heavyObject;
    > public [static] synchronized getHeavyObject () {
    > if (heavyObject==null) {
    > heavyObject = new HeavyObject();
    > }
    > return heavyObject;
    > }
    >
    > or the first-call synchronization implicit in class loading (singletons
    > only):
    >
    > class HeavyObjectGuardian {
    > static HeavyObject heavyObject = new HeavyObject();
    > }
    >
    > public static getHeavyObject () {
    > return HeavyObjectGuardian.heavyObject;
    > }
    >
    > Edge cases exist where the singleton needs to be released, but your
    > example doesn't help that in its current form - that would require safe
    > setting of the heavyObjectInit field, and so you're back to square one
    > synchronizing that.
    >
    > On a single or dual processor machine with a recent JVM, a synchronized
    > method call is only very slightly slower than an non-synchronized call -
    > DCL was an artifact to get round the slow synchronization in early JVMs.
    >
    > Speed was the only reason to use DCL in the first place. DCL compromised
    > deterministic thread safety with probabalistic thread safety (there are
    > no recorded examples of it failing, but it is theoretically possible) in
    > order to gain a speed advantage by not using synchronization, as
    > synchronization was costly at the time.
    >
    > Therefore alternatives to DCL must be deterministically thread safe (you
    > can still use DCL if you only need probable safety - if a plane journey
    > were as safe as a DCL access, then you could travel every day for a
    > million years and never crash), and either faster or simpler than the
    > two patterns above to be worthwhile. Those two examples are thread safe,
    > so execution speed is the *only* criteria to judge a different thread
    > safe pattern against them.
    >
    > Plot a graph showing how much faster your method is on single, dual and
    > multiple processors architectures when compared to the two normal
    > solutions above, and explain why the additional complexity is worth the
    > effort in a typical application, where method invocation overhead is a
    > very minor cost. Without profiling your pattern in a realistic
    > sscenario, there is nothing to judge its merit, and the simplist
    > solution wins.
    >
    > Pete




  7. #7
    Vinay Aggarwal Guest

    Re: Solving Lazy Initialization and double checked locking problem


    Hey Pete,

    I do agree with you on some points and disagree on others. You are
    correct that mostly this problem doesn't bother us in real world.
    Syncronizing the whole method usually is good enough. However I cannot
    say that every application in the world will be better off with
    syncronizing the get method. It may be true, it may not. I will
    let individual application authors decide what they want to use.
    I believe there are applications where reliability and responsiveness
    is much more important than solution complexity. For example
    stock trading applications or infrastructure pieces like EJB
    containers.

    My solution does seems complicated than DCL but well its the only
    deterministic alternative to method syncronization for instance based
    singletons. Individual application authors have to decide for
    themselves about how much do they stand to gain with different
    implementations. The performance can have huge variation depending on
    the application architecture. Hence any numbers I provide are
    probably not useful in real world.

    One of my motives of solving the problem was just to take a shot at
    a problem that experts say cannot be solved. Not only that, I also
    believe that this pattern can be used to solve other problems as
    well. For example, you mentioned that releasing the singletons is
    an issue for some cases. My solution can possibly be extended to
    solve such problems.

    This whole exercise could be just theoretical. Its out there
    in case somebody wants to use it. If there are efforts to change
    memory models and threading specifications to solve this problem,
    my solution probably interests somebody.

    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 /



    pete kirkham wrote:
    >
    > DCL is not much of a problem in the real world. AFAIK no-one has ever
    > given an example of a profiled application on a modern JVM where the
    > additional overhead of a synchronized call makes enough of a difference
    > to use complex DCL alternatives. Show me some code that
    > does something useful and has at least a 10% improvement in speed in its
    > critical path by making a faster synchronization mechanism for singletons.
    >
    > The common solutions to lazy creation are to use class/instance
    > synchronization (singletons and per-instance resources):
    >
    > [static] HeavyObject heavyObject;
    > public [static] synchronized getHeavyObject () {
    > if (heavyObject==null) {
    > heavyObject = new HeavyObject();
    > }
    > return heavyObject;
    > }
    >
    > or the first-call synchronization implicit in class loading (singletons
    > only):
    >
    > class HeavyObjectGuardian {
    > static HeavyObject heavyObject = new HeavyObject();
    > }
    >
    > public static getHeavyObject () {
    > return HeavyObjectGuardian.heavyObject;
    > }
    >
    > Edge cases exist where the singleton needs to be released, but your
    > example doesn't help that in its current form - that would require safe
    > setting of the heavyObjectInit field, and so you're back to square one
    > synchronizing that.
    >
    > On a single or dual processor machine with a recent JVM, a synchronized
    > method call is only very slightly slower than an non-synchronized call -
    > DCL was an artifact to get round the slow synchronization in early JVMs.
    >
    > Speed was the only reason to use DCL in the first place. DCL compromised
    > deterministic thread safety with probabalistic thread safety (there are
    > no recorded examples of it failing, but it is theoretically possible) in
    > order to gain a speed advantage by not using synchronization, as
    > synchronization was costly at the time.
    >
    > Therefore alternatives to DCL must be deterministically thread safe (you
    > can still use DCL if you only need probable safety - if a plane journey
    > were as safe as a DCL access, then you could travel every day for a
    > million years and never crash), and either faster or simpler than the
    > two patterns above to be worthwhile. Those two examples are thread safe,
    > so execution speed is the *only* criteria to judge a different thread
    > safe pattern against them.
    >
    > Plot a graph showing how much faster your method is on single, dual and
    > multiple processors architectures when compared to the two normal
    > solutions above, and explain why the additional complexity is worth the
    > effort in a typical application, where method invocation overhead is a
    > very minor cost. Without profiling your pattern in a realistic
    > sscenario, there is nothing to judge its merit, and the simplist
    > solution wins.
    >
    > Pete




  8. #8
    Vinay Aggarwal Guest

    Re: Solving Lazy Initialization and double checked locking problem


    Hey Pete,

    I do agree with you on some points and disagree on others. You are
    correct that mostly this problem doesn't bother us in real world.
    Syncronizing the whole method usually is good enough. However I cannot
    say that every application in the world will be better off with
    syncronizing the get method. It may be true, it may not. I will
    let individual application authors decide what they want to use.
    I believe there are applications where reliability and responsiveness
    is much more important than solution complexity. For example
    stock trading applications or infrastructure pieces like EJB
    containers.

    My solution does seems complicated than DCL but well its the only
    deterministic alternative to method syncronization for instance based
    singletons. Individual application authors have to decide for
    themselves about how much do they stand to gain with different
    implementations. The performance can have huge variation depending on
    the application architecture. Hence any numbers I provide are
    probably not useful in real world.

    One of my motives of solving the problem was just to take a shot at
    a problem that experts say cannot be solved. Not only that, I also
    believe that this pattern can be used to solve other problems as
    well. For example, you mentioned that releasing the singletons is
    an issue for some cases. My solution can possibly be extended to
    solve such problems.

    This whole exercise could be just theoretical. Its out there
    in case somebody wants to use it. If there are efforts to change
    memory models and threading specifications to solve this problem,
    my solution probably interests somebody.

    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 /



    pete kirkham wrote:
    >
    > DCL is not much of a problem in the real world. AFAIK no-one has ever
    > given an example of a profiled application on a modern JVM where the
    > additional overhead of a synchronized call makes enough of a difference
    > to use complex DCL alternatives. Show me some code that
    > does something useful and has at least a 10% improvement in speed in its
    > critical path by making a faster synchronization mechanism for singletons.
    >
    > The common solutions to lazy creation are to use class/instance
    > synchronization (singletons and per-instance resources):
    >
    > [static] HeavyObject heavyObject;
    > public [static] synchronized getHeavyObject () {
    > if (heavyObject==null) {
    > heavyObject = new HeavyObject();
    > }
    > return heavyObject;
    > }
    >
    > or the first-call synchronization implicit in class loading (singletons
    > only):
    >
    > class HeavyObjectGuardian {
    > static HeavyObject heavyObject = new HeavyObject();
    > }
    >
    > public static getHeavyObject () {
    > return HeavyObjectGuardian.heavyObject;
    > }
    >
    > Edge cases exist where the singleton needs to be released, but your
    > example doesn't help that in its current form - that would require safe
    > setting of the heavyObjectInit field, and so you're back to square one
    > synchronizing that.
    >
    > On a single or dual processor machine with a recent JVM, a synchronized
    > method call is only very slightly slower than an non-synchronized call -
    > DCL was an artifact to get round the slow synchronization in early JVMs.
    >
    > Speed was the only reason to use DCL in the first place. DCL compromised
    > deterministic thread safety with probabalistic thread safety (there are
    > no recorded examples of it failing, but it is theoretically possible) in
    > order to gain a speed advantage by not using synchronization, as
    > synchronization was costly at the time.
    >
    > Therefore alternatives to DCL must be deterministically thread safe (you
    > can still use DCL if you only need probable safety - if a plane journey
    > were as safe as a DCL access, then you could travel every day for a
    > million years and never crash), and either faster or simpler than the
    > two patterns above to be worthwhile. Those two examples are thread safe,
    > so execution speed is the *only* criteria to judge a different thread
    > safe pattern against them.
    >
    > Plot a graph showing how much faster your method is on single, dual and
    > multiple processors architectures when compared to the two normal
    > solutions above, and explain why the additional complexity is worth the
    > effort in a typical application, where method invocation overhead is a
    > very minor cost. Without profiling your pattern in a realistic
    > sscenario, there is nothing to judge its merit, and the simplist
    > solution wins.
    >
    > Pete




  9. #9
    Vinay Aggarwal Guest

    Re: Solving Lazy Initialization and double checked locking problem


    Hey Pete,

    I do agree with you on some points and disagree on others. You are
    correct that mostly this problem doesn't bother us in real world.
    Syncronizing the whole method usually is good enough. However I cannot
    say that every application in the world will be better off with
    syncronizing the get method. It may be true, it may not. I will
    let individual application authors decide what they want to use.
    I believe there are applications where reliability and responsiveness
    is much more important than solution complexity. For example
    stock trading applications or infrastructure pieces like EJB
    containers.

    My solution does seems complicated than DCL but well its the only
    deterministic alternative to method syncronization for instance based
    singletons. Individual application authors have to decide for
    themselves about how much do they stand to gain with different
    implementations. The performance can have huge variation depending on
    the application architecture. Hence any numbers I provide are
    probably not useful in real world.

    One of my motives of solving the problem was just to take a shot at
    a problem that experts say cannot be solved. Not only that, I also
    believe that this pattern can be used to solve other problems as
    well. For example, you mentioned that releasing the singletons is
    an issue for some cases. My solution can possibly be extended to
    solve such problems.

    This whole exercise could be just theoretical. Its out there
    in case somebody wants to use it. If there are efforts to change
    memory models and threading specifications to solve this problem,
    my solution probably interests somebody.

    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 /



    pete kirkham wrote:
    >
    > DCL is not much of a problem in the real world. AFAIK no-one has ever
    > given an example of a profiled application on a modern JVM where the
    > additional overhead of a synchronized call makes enough of a difference
    > to use complex DCL alternatives. Show me some code that
    > does something useful and has at least a 10% improvement in speed in its
    > critical path by making a faster synchronization mechanism for singletons.
    >
    > The common solutions to lazy creation are to use class/instance
    > synchronization (singletons and per-instance resources):
    >
    > [static] HeavyObject heavyObject;
    > public [static] synchronized getHeavyObject () {
    > if (heavyObject==null) {
    > heavyObject = new HeavyObject();
    > }
    > return heavyObject;
    > }
    >
    > or the first-call synchronization implicit in class loading (singletons
    > only):
    >
    > class HeavyObjectGuardian {
    > static HeavyObject heavyObject = new HeavyObject();
    > }
    >
    > public static getHeavyObject () {
    > return HeavyObjectGuardian.heavyObject;
    > }
    >
    > Edge cases exist where the singleton needs to be released, but your
    > example doesn't help that in its current form - that would require safe
    > setting of the heavyObjectInit field, and so you're back to square one
    > synchronizing that.
    >
    > On a single or dual processor machine with a recent JVM, a synchronized
    > method call is only very slightly slower than an non-synchronized call -
    > DCL was an artifact to get round the slow synchronization in early JVMs.
    >
    > Speed was the only reason to use DCL in the first place. DCL compromised
    > deterministic thread safety with probabalistic thread safety (there are
    > no recorded examples of it failing, but it is theoretically possible) in
    > order to gain a speed advantage by not using synchronization, as
    > synchronization was costly at the time.
    >
    > Therefore alternatives to DCL must be deterministically thread safe (you
    > can still use DCL if you only need probable safety - if a plane journey
    > were as safe as a DCL access, then you could travel every day for a
    > million years and never crash), and either faster or simpler than the
    > two patterns above to be worthwhile. Those two examples are thread safe,
    > so execution speed is the *only* criteria to judge a different thread
    > safe pattern against them.
    >
    > Plot a graph showing how much faster your method is on single, dual and
    > multiple processors architectures when compared to the two normal
    > solutions above, and explain why the additional complexity is worth the
    > effort in a typical application, where method invocation overhead is a
    > very minor cost. Without profiling your pattern in a realistic
    > sscenario, there is nothing to judge its merit, and the simplist
    > solution wins.
    >
    > Pete




  10. #10
    Vinay Aggarwal Guest

    Re: Solving Lazy Initialization and double checked locking problem


    Hey Pete,

    I do agree with you on some points and disagree on others. You are
    correct that mostly this problem doesn't bother us in real world.
    Syncronizing the whole method usually is good enough. However I cannot
    say that every application in the world will be better off with
    syncronizing the get method. It may be true, it may not. I will
    let individual application authors decide what they want to use.
    I believe there are applications where reliability and responsiveness
    is much more important than solution complexity. For example
    stock trading applications or infrastructure pieces like EJB
    containers.

    My solution does seems complicated than DCL but well its the only
    deterministic alternative to method syncronization for instance based
    singletons. Individual application authors have to decide for
    themselves about how much do they stand to gain with different
    implementations. The performance can have huge variation depending on
    the application architecture. Hence any numbers I provide are
    probably not useful in real world.

    One of my motives of solving the problem was just to take a shot at
    a problem that experts say cannot be solved. Not only that, I also
    believe that this pattern can be used to solve other problems as
    well. For example, you mentioned that releasing the singletons is
    an issue for some cases. My solution can possibly be extended to
    solve such problems.

    This whole exercise could be just theoretical. Its out there
    in case somebody wants to use it. If there are efforts to change
    memory models and threading specifications to solve this problem,
    my solution probably interests somebody.

    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 /



    pete kirkham wrote:
    >
    > DCL is not much of a problem in the real world. AFAIK no-one has ever
    > given an example of a profiled application on a modern JVM where the
    > additional overhead of a synchronized call makes enough of a difference
    > to use complex DCL alternatives. Show me some code that
    > does something useful and has at least a 10% improvement in speed in its
    > critical path by making a faster synchronization mechanism for singletons.
    >
    > The common solutions to lazy creation are to use class/instance
    > synchronization (singletons and per-instance resources):
    >
    > [static] HeavyObject heavyObject;
    > public [static] synchronized getHeavyObject () {
    > if (heavyObject==null) {
    > heavyObject = new HeavyObject();
    > }
    > return heavyObject;
    > }
    >
    > or the first-call synchronization implicit in class loading (singletons
    > only):
    >
    > class HeavyObjectGuardian {
    > static HeavyObject heavyObject = new HeavyObject();
    > }
    >
    > public static getHeavyObject () {
    > return HeavyObjectGuardian.heavyObject;
    > }
    >
    > Edge cases exist where the singleton needs to be released, but your
    > example doesn't help that in its current form - that would require safe
    > setting of the heavyObjectInit field, and so you're back to square one
    > synchronizing that.
    >
    > On a single or dual processor machine with a recent JVM, a synchronized
    > method call is only very slightly slower than an non-synchronized call -
    > DCL was an artifact to get round the slow synchronization in early JVMs.
    >
    > Speed was the only reason to use DCL in the first place. DCL compromised
    > deterministic thread safety with probabalistic thread safety (there are
    > no recorded examples of it failing, but it is theoretically possible) in
    > order to gain a speed advantage by not using synchronization, as
    > synchronization was costly at the time.
    >
    > Therefore alternatives to DCL must be deterministically thread safe (you
    > can still use DCL if you only need probable safety - if a plane journey
    > were as safe as a DCL access, then you could travel every day for a
    > million years and never crash), and either faster or simpler than the
    > two patterns above to be worthwhile. Those two examples are thread safe,
    > so execution speed is the *only* criteria to judge a different thread
    > safe pattern against them.
    >
    > Plot a graph showing how much faster your method is on single, dual and
    > multiple processors architectures when compared to the two normal
    > solutions above, and explain why the additional complexity is worth the
    > effort in a typical application, where method invocation overhead is a
    > very minor cost. Without profiling your pattern in a realistic
    > sscenario, there is nothing to judge its merit, and the simplist
    > solution wins.
    >
    > Pete





    •    Sponsored Ads



Latest Article

Network Security Risk Assessment and Measurement

Read More...