I discovered a pattern i was using, that is not correct:
public static Singleton getInstance()
{
if (null == instance)
{
synchronized(Singleton.class)
{
if (null == instance)
{
instance = new Singleton();
}
}
}
}
... to avoid synchronization (=slow) when the singleton exists (= most of the cases).
This is NOT GOOD, it does not work!
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
I wonder, if this usage below is also NOT correct: i have a singleton factory method that hold a Map (ContextMap.vm is just a Map) of named singletons.
I believe this usage is ok, but after i read about the previous article, i'm in doubt.
public static Object singleton(Object name,Transform factory,Object args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, java.lang.reflect.InvocationTargetException, Exception
{
Object object = ContextMap.vm.get(name);
if (object == null)
{
synchronized(ContextMap.vm)
{
object = ContextMap.vm.get(name);
if (object == null)
{
object = factory.transform(args);
ContextMap.vm.put(name,object);
}
}
}
return object;
}
Any idea's on this?
-
Double Checked Locking (4 messages)
- Posted by: Dieter Cailliau
- Posted on: July 08 2002 08:37 EDT
Threaded Messages (4)
- Double Checked Locking by tim fox on July 08 2002 18:35 EDT
- Double Checked Locking by tim fox on July 08 2002 18:42 EDT
-
Double Checked Locking by Dieter Cailliau on July 15 2002 09:53 EDT
- Double Checked Locking by tim fox on November 29 2002 10:39 EST
-
Double Checked Locking by Dieter Cailliau on July 15 2002 09:53 EDT
- Double Checked Locking by tim fox on July 08 2002 18:42 EDT
-
Double Checked Locking[ Go to top ]
- Posted by: tim fox
- Posted on: July 08 2002 18:35 EDT
- in response to Dieter Cailliau
Hi -
it looks like your second example will have the same problems as the first.
solution 1 would be to acquire the mutex before the test of = null.
you can do this by making the method synchronized, or putting the synchronized(object) block before the test - they will produce the same code.
as you mentioned there is a slight performance hit by doing this.
in my experience the performance hit is not *that* big, but if it is very important in your system, you could consider creating the singleton instance in a static initializer - by doing so, you will ensure the object is never null in the getter method, and you won't require the mutex.
eg.
public class Singleton
{
-
Double Checked Locking[ Go to top ]
- Posted by: tim fox
- Posted on: July 08 2002 18:42 EDT
- in response to tim fox
Ooops! I pressed submit to soon!
Here is the rest of the message:
Hi -
it looks like your second example will have the same problems as the first.
solution 1 would be to acquire the mutex before the test of = null.
you can do this by making the method synchronized, or putting the synchronized(object) block before the test - they will produce the same code.
as you mentioned there is a slight performance hit by doing this.
in my experience the performance hit is not *that* big, but if it is very important in your system, you could consider creating the singleton instance in a static initializer - by doing so, you will ensure the object is never null in the getter method, and you won't require the mutex.
I think this should work:
eg.
public class Singleton
{
private static Singleton _instance;
static
{
init();
}
private static synchronized init()
{
if (_instance == null)
{
_instance = new Singleton();
}
}
public static Singleton getInstance()
{
return _instance;
}
}
You may not need to test for instance == null in the init() method, or synchronize it but I've put it in just in case, it could get called more than once, I can't remember if that's possible off the top of my head - if in doubt I'd check the Java language specification.
(I imagine it would be called the first time the class is instantiated, per classloader).
Hope that helps
-
Double Checked Locking[ Go to top ]
- Posted by: Dieter Cailliau
- Posted on: July 15 2002 09:53 EDT
- in response to tim fox
no! i don't understand why my solution is not good: since ContextMap.vm.get(name) is a method invocation, it will be executed once outside and once inside the synchronized block. I don't see where this can suffer from the problem with double checked locking. I can not imagine an optimizing compiler that translates this into code that is not equivalent to what i intended to do, because it does have to call the method twice, and the second call is inside synchronization. What's the problem? -
Double Checked Locking[ Go to top ]
- Posted by: tim fox
- Posted on: November 29 2002 10:39 EST
- in response to Dieter Cailliau
This article should shed some light onto why your method still does not work.
http://www-106.ibm.com/developerworks/java/library/j-dcl.html?dwzone=java