[concurrency-interest] AtomicBoolean and Double-Checking Locking? Is this Singleton safe?

John D. Heintz jheintz at gmail.com
Tue Jun 28 15:36:27 EDT 2005


Thanks Jeremy for verifying that assumption.

I used Singleton as a clear/obvious example of what I'm really trying
to do. You're right, either volatile or using the
"Initialize-On-Demand Holder Class idiom" would both be more
straightforward and rational for a Singleton.

I want to use Annotations to support lazy loading "services" from an
IOC container, but to do so in an efficient and thread-safe way. I
basically want "write once" fields (I think they're sometimes called
logic variables).

Now that my assumptions for AtomicBoolean are verified I can throw
together a simple proof of concept. I'll basically need an
AtomicBoolean for each field (per instance or per class for statics)
to check for the "already initialized" condition. I'm starting with
AspectJ for this, but am seeing that AspectJ doesn't generalize over
fields as well as I would like. It looks like I'll need to have a per
instance (or per class for statics) ConcurrentHashMap to lookup the
_right_ AtomicBoolean object for each field for each instance.

For example:
class FooService {
  @Obtain("emailService")
  private IEmailService _emailService;

  @Obtain("jndi:dataSourceXYZ")
  private DataSource _dataSource;

  public void doSomething() {
    _dataSource.getConnection()......

    _emailService.send("", "", ...);
  }
}

The two fields here should be lazy-loadable, thread-safe, and efficient. 

I picked up this style from PEAK (a python component app framework
with very sophisticated composition mechanisms). See
http://peak.telecommunity.com/DevCenter/IntroToPeak_2fLessonOne for
more details, but this is an example of some PEAK python service code:

class Foo:
    service = binding.Obtain(PropertyName('helloworld.service'))

    def doSomething(self, args):
        self.service(args)
        .....

The idea is that each component declares it's dependencies (here with
a PropertyName but anything can be a key: JNDI name, Interface type,
...)  Components are then bound together in a hierarchical context
where these bindings are resolved. Python has a global interpreter
lock so threads don't run concurrently. That's great everywhere
(simplifies a bunch of things) but SMP machines of course.

Thanks for the verification! If anyone's interested I'll let you know
how it turns out.
John

On 6/28/05, Jeremy Manson <jmanson at cs.purdue.edu> wrote:
> Hi John,
> 
> This is safe, in the sense that AtomicBooleans can be used for volatiles.
> It would probably make somewhat more sense to use AtomicReference
> rather than AtomicBoolean.
> 
> Having said that, I am not sure this is a good idea.  Not all platforms are
> guaranteed
> to support efficient AtomicXXXs.  The code is uglier than the simple use
> of volatile, which is designed to work correctly in this case.
> Where is the win here?
> 
>                                         Jeremy
> 
> On Tue, Jun 28, 2005 at 01:17:15PM -0500, John D. Heintz wrote:
> > Hello all,
> >
> > I've been waiting for a bunch of new Double-Checked locking articles
> > to come out since the release of the java.util.concurrent.atomic
> > package, but I've seen very little ;-)
> >
> > The most recent discussion I could find was
> > http://altair.cs.oswego.edu/pipermail/concurrency-interest/2005-May/001472.html,
> > but of course I may have missed something.
> >
> > I have a simple question: can an AtomicBoolean check _safely_ replace
> > the '== null' from yester-years un-safe Double-Checked Locking
> > Singleton idiom?
> >
> > Here's an example Singleton implementation to show what I mean.
> > ================================================
> > import java.util.concurrent.atomic.AtomicBoolean;
> >
> > public class Singleton {
> >       static Singleton _instance;
> >       static AtomicBoolean _instanceFlag = new AtomicBoolean(false);
> >
> >       public Singleton() {
> >
> >       }
> >
> >       static Singleton getInstance() {
> >               if (_instanceFlag.get() != true) {
> >
> >                       synchronized (_instanceFlag) { // block others until finished constructing
> >                               // double check
> >                               if (_instanceFlag.get() != true) {
> >                                       _instance = new Singleton();
> >
> >                                       if (!_instanceFlag.compareAndSet(false, true)) {
> >                                               throw new IllegalStateException("Ack! Can't fail this call!!!");
> >                                       }
> >                               }
> >                       }
> >
> >               }
> >               return _instance;
> >       }
> > }
> > ===============================================
> >
> >
> > Thanks all,
> > John
> >
> > --
> > John D. Heintz
> > Software Craftsman
> > Austin, TX
> > (512) 633-1198
> >
> > jheintz at pobox.com
> > http://johnheintz.homeip.net
> >
> > _______________________________________________
> > Concurrency-interest mailing list
> > Concurrency-interest at altair.cs.oswego.edu
> > http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
> 
> 


-- 
John D. Heintz
Software Craftsman
Austin, TX
(512) 633-1198

jheintz at pobox.com
http://johnheintz.homeip.net



More information about the Concurrency-interest mailing list