You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@turbine.apache.org by Pete Kazmier <pe...@kazmier.com> on 2002/03/13 13:55:16 UTC

JCS - Double-check idiom?

While reading item #48 in the Effective Java book, I came across a few
paragraphs that discuss the potential pitfalls of using the double-check
idiom in a multi-threaded application.  I recall seeing in the commit
logs that this idiom has been used in JCS.  As a result, I believe there
could be problems using JCS in a production environment.  However, I'm
by no means an expert in the subject matter, I'd appreciate opinions
from others.

For those of you with Bloch's book, please refer to pages 193 - 195.
The code that he refers to is the following (he doesn't follow our
coding convention :-)

   private static Foo foo = null;
   
   public static Foo getFoo() {
       if (foo == null) {
           synchronized (Foo.class) {
               if (foo == null)
                   foo = new Foo();
           }
       }
       return foo;
   }

Then the last paragraph on page 193 states:

  "That a thread can observe the lazily constructed object in a
   partially initialized state is wildly counterintuitive.  The object
   is fully constructed before the reference is "published" in the field
   from which it is read by other threads (foo).  But in the abscence of
   synchronization, reading a "published" object reference does not
   guarantee that a thread will see all of the data that were stored in
   memory prior to the publication of the object reference.  In
   particular, reading a published object reference does not guarantee
   that the reading thread will see the most recent values of the data
   that constitute the internals of the referenced object.  In general,
   the double-check idiom does not work, although it does work if the
   shared variable contains a primitative value rather than an object
   reference [Pugh01b]."

Earlier in that section, he also states that problems of this nature
are much more likely to occur on multi-processor machines.  

JCS uses a similiar idiom in several locations, for example, in
o.a.s.jcs.access.CacheAccess, the following appears:

   if ( cacheMgr == null )
   {
       synchronized ( CacheAccess.class )
       {
           if ( cacheMgr == null )
           {
               cacheMgr = CacheManagerFactory.getInstance();
           }
       }
   }

Does the problem Bloch describes apply here as well?

Thanks,
Pete

-- 
Peter Kazmier                                 http://www.kazmier.com
PGP Fingerprint   4FE7 8DA3 D0B5 9CAA 69DC  7243 1855 BC2E 4B43 5654

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: JCS - Double-check idiom?

Posted by Jon Scott Stevens <jo...@latchkey.com>.
on 3/13/02 2:51 PM, "James Taylor" <jt...@4lane.com> wrote:

> Sorry, I wasn't clear at all,
> 
> Consider the class in question: org.apache.stratum.jcs.JCS
> 
>   protected static void ensureCacheManager()
>   {
>       if ( cacheMgr == null )
>       {
>           synchronized ( GroupCacheAccess.class )
>           {
>               if ( cacheMgr == null )
>               {
>                   if ( configFilename == null )
>                   {
>                       cacheMgr = GroupCacheManagerFactory.getInstance();
>                   }
>                   else
>                   {
>                       cacheMgr = GroupCacheManagerFactory
>                           .getInstance( configFilename );
>                   }
>               }
>           }
>       }
>   }
> 
>   public static void setConfigFilename( String configFilename )
>   {
>       JCS.configFilename = configFilename;
>   }
> 
> So we need to be able to call getFilename and then ensureCacheManager
> later. Of course, there are other problems here, a change in
> architecture might be a better way to work around this concern. As we
> work on more runtime configuration flexibility I think we will be able
> to find a better solution. For now removing the double check and making
> ensureCacheManager synchronized seems like the safest option.

Yes, the above looks like bad design. I didn't realize the scope of it. :-)

> That can't possibly be true for a static variable. My understanding is
> that static initialization is done at the time of first active use,
> which is too early for the above to work unfortunately.

Ah...yes...true...

-jon


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: JCS - Double-check idiom?

Posted by James Taylor <jt...@4lane.com>.
Sorry, I wasn't clear at all,

Consider the class in question: org.apache.stratum.jcs.JCS

    protected static void ensureCacheManager()
    {
        if ( cacheMgr == null )
        {
            synchronized ( GroupCacheAccess.class )
            {
                if ( cacheMgr == null )
                {
                    if ( configFilename == null )
                    {
                        cacheMgr = GroupCacheManagerFactory.getInstance();
                    }
                    else
                    {
                        cacheMgr = GroupCacheManagerFactory
                            .getInstance( configFilename );
                    }
                }
            }
        }
    }

    public static void setConfigFilename( String configFilename )
    {
        JCS.configFilename = configFilename;
    }

So we need to be able to call getFilename and then ensureCacheManager
later. Of course, there are other problems here, a change in
architecture might be a better way to work around this concern. As we
work on more runtime configuration flexibility I think we will be able
to find a better solution. For now removing the double check and making
ensureCacheManager synchronized seems like the safest option.

> > Unfortunately JCS requires predictable initialization orders in a lot of
> > these cases (things must be configured before getCacheManager is called
> > for example). I don't know how safe it is to rely on the classloader for
> > this case. It seems like we have to incur the cost of synchronizing the
> > 'ensureCacheManager' method if we want to be truly safe.
> > 
> > Thanks,
> > James
> 
> The initialization of the static{} is predictable. In fact, it is documented
> that it happens before the constructor is called. Read the Java language
> spec.

That can't possibly be true for a static variable. My understanding is
that static initialization is done at the time of first active use,
which is too early for the above to work unfortunately.

Clever solutions welcome of course.

-- jt


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: JCS - Double-check idiom?

Posted by Jon Scott Stevens <jo...@latchkey.com>.
on 3/13/02 1:50 PM, "James Taylor" <jt...@4lane.com> wrote:

> Unfortunately JCS requires predictable initialization orders in a lot of
> these cases (things must be configured before getCacheManager is called
> for example). I don't know how safe it is to rely on the classloader for
> this case. It seems like we have to incur the cost of synchronizing the
> 'ensureCacheManager' method if we want to be truly safe.
> 
> Thanks,
> James

The initialization of the static{} is predictable. In fact, it is documented
that it happens before the constructor is called. Read the Java language
spec.

-jon


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: JCS - Double-check idiom?

Posted by James Taylor <jt...@4lane.com>.
Unfortunately JCS requires predictable initialization orders in a lot of
these cases (things must be configured before getCacheManager is called
for example). I don't know how safe it is to rely on the classloader for
this case. It seems like we have to incur the cost of synchronizing the
'ensureCacheManager' method if we want to be truly safe.

Thanks,
James

On Wed, 2002-03-13 at 16:44, Jon Scott Stevens wrote:
> on 3/13/02 4:55 AM, "Pete Kazmier" <pe...@kazmier.com> wrote:
> 
> >  private static Foo foo = null;
> >  
> >  public static Foo getFoo() {
> >      if (foo == null) {
> >          synchronized (Foo.class) {
> >              if (foo == null)
> >                  foo = new Foo();
> >          }
> >      }
> >      return foo;
> >  }
> 
> One way to deal with this is to write it like this:
> 
> public class FooManager
> {
>     private static Foo foo = null;
> 
>     static
>     {
>         foo = new Foo();
>     }
> 
>     public static Foo getFoo()
>     {
>         return foo;
>     }
> }
> 
> That way, no sync needs to happen anyway.
> 
> -jon
> 
> 
> --
> To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
> For additional commands, e-mail: <ma...@jakarta.apache.org>
> 
> 



--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: JCS - Double-check idiom?

Posted by Jon Scott Stevens <jo...@latchkey.com>.
on 3/13/02 4:55 AM, "Pete Kazmier" <pe...@kazmier.com> wrote:

>  private static Foo foo = null;
>  
>  public static Foo getFoo() {
>      if (foo == null) {
>          synchronized (Foo.class) {
>              if (foo == null)
>                  foo = new Foo();
>          }
>      }
>      return foo;
>  }

One way to deal with this is to write it like this:

public class FooManager
{
    private static Foo foo = null;

    static
    {
        foo = new Foo();
    }

    public static Foo getFoo()
    {
        return foo;
    }
}

That way, no sync needs to happen anyway.

-jon


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>