3

I'm seeking an answer to a question similar to Is it appropriate to use AtomicReference.compareAndSet to set a reference to the results of a database call? but with different requirement.

The goal is to create an instance of ObjectWithSideEffectConstructor only once to avoid duplicate side effects. The construction must happen in setUp(). Multiple threads will call setUp(). Similarly there will be a tearDown() for reclaiming the resource from the object, which is omitted here. Question: what is the best practice to achieve the goal?

Simply using AtomicReference will not be enough, because the constructor will be executed first, so as the side effect.

private static AtomicReference<ObjectWithSideEffectConstructor> ref =
  new AtomicReference<ObjectWithSideEffectConstructor>()

void setUp() {
  ref.compareAndSet(null, new ObjectWithSideEffectConstructor());
}

Using the answer from Is it appropriate to use AtomicReference.compareAndSet to set a reference to the results of a database call? will not work, because volatile lacks of synchronization. There will be window that multiple threads enters if.

private static volatile ObjectWithSideEffectConstructor obj;

void setUp() {
  if (obj == null) obj = new ObjectWithSideEffectConstructor();
}

Simple fix would be

private static ObjectWithSideEffectConstructor obj;
private static final Object monitor = new Object();

void setUp() {
  synchronized (monitor) {
    if (obj == null) obj = new ObjectWithSideEffectConstructor();
  }
}

Similarly, DCL with volatile monitor may give better read performance. But both requires some level of synchronization, thus expect worse performance.

Also we can use FutureTask. It is more efficient because once the object is created, subsequent FutureTask.get() will return without blocking. But it is definitely much more complicated than synchronized.

private static final AtomicReference<FutureTask<ObjectWithSideEffectConstructor>> ref =
  new AtomicReference<FutureTask<ObjectWithSideEffectConstructor>>();

void setUp() {
  final FutureTask<ObjectWithSideEffectConstructor> future =
    new FutureTask<ObjectWithSideEffectConstructor>(
      new Callable<ObjectWithSideEffectConstructor>() {
        @Override
        public ObjectWithSideEffectConstructor call() throws InterruptedException {
          return new ObjectWithSideEffectConstructor();
        }
      }
    );
  if (ref.compareAndSet(null, future)) future.run();
  ref.get().get();
}

Thanks for suggestions.

Community
  • 1
  • 1
Reci
  • 4,099
  • 3
  • 37
  • 42
  • 4
    Use an enum? http://stackoverflow.com/questions/70689/what-is-an-efficient-way-to-implement-a-singleton-pattern-in-java – assylias Oct 12 '13 at 09:53
  • Can you explain? Do you mean to wrap `ObjectWithSideEffectConstructor` in an enum-singleton? How do you know if the `ObjectWithSideEffectConstructor` is constructed or not? – Reci Oct 13 '13 at 12:23
  • `enum ObjectWithSideEffectConstructor {INSTANCE; private ObjectWithSideEffectConstructor() { /*your constructor here */}}` The constructor will not be called until the enum is loaded, which will happen the first time your code calls `ObjectWithSideEffectConstructor.INSTANCE`. – assylias Oct 13 '13 at 14:12
  • After reading http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.2, I believe it is guaranteed that the constructor will be called only once. But because I need a thread-safe `tearDown()`, for symmetry I'd prefer `synchronized` approach. Thanks! – Reci Oct 14 '13 at 18:57
  • Yes the JLS guarantees that the constructor will only be called once. Nothing prevents you from adding a `public void tearDown()` method in the enum... – assylias Oct 14 '13 at 21:13
  • Problem is how to let multiple threads call `tearDown()` safely. I think I need to synchronize `tearDown()`, unless you have better idea. – Reci Oct 14 '13 at 21:21
  • I suppose it won't be called too often so performance does not matter and synchronized seems to be the easiest way. – assylias Oct 14 '13 at 22:52

6 Answers6

3

If you're talking about threadsafe lazy initialization of the singleton, here is a cool code pattern to use that accomplishes 100% threadsafe lazy initialization without any synchronization code:

public class MySingleton {

     private static class MyWrapper {
         static MySingleton INSTANCE = new MySingleton();
     }

     private MySingleton () {}

     public static MySingleton getInstance() {
         return MyWrapper.INSTANCE;
     }
}

This coding pattern is known as the Initialization-on-demand holder idiom. It will instantiate the singleton only when getInstance() is called, and it's 100% threadsafe! It's a classic.

It works because the class loader has its own synchronization for handling static initialization of classes: You are guaranteed that all static initialization has completed before the class is used, and in this code the class is only used within the getInstance() method, so that's when the class loaded loads the inner class.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • Interesting technique, but is this much (or any?) faster than a 'synchronized static' method with an `if (instance == null)` initialization block? It obviously relies on some form of synchronization or concurrency under the hood, I'm just wondering whether the more-obscure code form actually delivers any performance benefit. Any measurements? – Thomas W Oct 17 '13 at 08:39
  • Well, some quick measurements.. not a proper benchmark, but I'm getting 858 ms for a simple "static synchronized" lazy-init method, and 33.4 ms for the "inner class" lazy-singleton technique.. **that's 25 times faster,** if timings are not deceiving me. Kudos. – Thomas W Oct 17 '13 at 09:00
  • I probably need to benchmark myself for sure. I'm interested in how you measure the performance. – Reci Jan 04 '14 at 10:40
  • Sure! Here's an article on the approach, and how I benchmarked it: http://literatejava.com/jvm/fastest-threadsafe-singleton-jvm/ – Thomas W Apr 08 '14 at 09:56
1

Implementing Singleton in Java 5 or above version using Enum:

Enum is thread safe and implementation of Singleton through Enum ensures that your singleton will have only one instance even in a multithreaded environment. Let us see a simple implementation:

public enum SingletonEnum 
{
    INSTANCE;
    public void doStuff()
    {
        System.out.println("Singleton using Enum");
    }
}

// How to use in other classes
public static void main(String[] args) 
{
    SingletonEnum.INSTANCE.doStuff();
}
Matthias
  • 3,582
  • 2
  • 30
  • 41
  • 1
    Enum is good for singleton does not need destruction. In my case, I need thread-safe destruction. – Reci Oct 15 '13 at 21:00
1

Always use the enum type for singletons, not only does it enforce the singleton elegantly, it also prevents common programming errors like when a singleton inherits a clone() method from its superclass and the programmer forgets to override it with a private method declaration. Or when you forget to override deserialisable, and allow programmers to serialise your singleton, declare a new instance, and then deserialise the old one.

Alternatively, if you use a static factory pattern, you can declare instance fields transient and use a readresolve method. This provides the flexibility if you might change your mind about whether it should be a singleton later in the design process.

Credit: Answer based on Effective Java by J Bloch (Item 3), a book every Java programmer should read, own and refer to regularly...

phil_20686
  • 4,000
  • 21
  • 38
0

I assume you only want one ObjectWithSideEffectConstructor. There's a question here as to whether 1) it's the side effect happening twice your want to avoid, or 2) you just need to end up with a consistent (singleton) reference.

Either way, synchronized is a good standard option. It will keep other threads from constructing a second instance, while the first thread is in setup.

If you're in situation 1), using synchronized is probably required. If performance after startup were critical, you could possibly consider preceding the synchronized section with an AtomicReference.get() fast-path, to enable the synchronized section to be avoided after startup is complete.

If you're in situation 2), then -- it's not really clear from your question -- there is a side-effect of construction, but you don't care about duplicating that -- just so long as the client code only "sees" a consistent single reference.

In that second case, you could use AtomicReference.get() to check whether it's already initialized, and return if so. Threads would then enter the "race section" where they would construct (potentially multiple) ObjectWithSideEffectConstructor. Lastly, there would be a compareAndSet so that only one thread set the singleton.. with failing threads falling back to anAtomicReference.get() to take the correct singleton.

Performancewise, a single call to AtomicReference is faster than a synchronized block -- but I'm not sure if, with the double- and triple-checking & construction of unwanted side-effect objects, the second approach would be. A simple synchronized block might, again, be simpler & faster.

I'd be interested to see some measurements.

Thomas W
  • 13,940
  • 4
  • 58
  • 76
  • It is 1) I'm trying to avoid. Updated question to clarify. – Reci Oct 12 '13 at 00:17
  • Essentially then, you need to _block_ other threads from entering the "Object with side effect" construction section. `synchronized` would be the simplest mechanism to block them, which I would believe to be the best. You "could" supplement this with an `AtomicReference.get()` to avoid the synchronized block after startup, if performance was critical? At startup, all threads but one must block so performance there cannot be important. – Thomas W Oct 12 '13 at 00:24
  • See @Bohemian's technique -- it appears it may be a winner if you need performance. – Thomas W Oct 17 '13 at 09:01
0

The synchronized method would be the way to go. If you actually need the performance you need to restructure your code to have a single-threaded pre-initialization. Using any other form will cause side-effects as described in the singleton pattern.

TwoThe
  • 13,879
  • 6
  • 30
  • 54
0

For what it's worth, the FutureTask approach doesn't actually require all of that code; the AtomicReference is not needed, and there shouldn't be any need to call both run() and get(). So you can simplify it slightly:

private static final Future<ObjectWithSideEffectConstructor> future =
  new FutureTask<>(
    new Callable<ObjectWithSideEffectConstructor>() {
      @Override
      public ObjectWithSideEffectConstructor call() throws InterruptedException {
        return new ObjectWithSideEffectConstructor();
      }
    }
  );

void setUp() {
  future.run(); // or future.get(), if you want to get any exception immediately
}

Furthermore, with Java 8, the initialization expression can be written much more briefly; the above can be reduced to just:

private static final Future<ObjectWithSideEffectConstructor> future =
  new FutureTask<>(ObjectWithSideEffectConstructor::new);

void setUp() {
  future.run(); // or future.get(), if you want to get any exception immediately
}
ruakh
  • 175,680
  • 26
  • 273
  • 307