| Author |
Double-checked locking and the Singleton pattern ?
|
Andy Jung
Ranch Hand
Joined: Feb 07, 2010
Posts: 150
|
|
Howdy,
trying to implement a thread-safe singleton using the double-checked locking technique my IDE (NetBeans IDE 6.7.1) automatically detects my intention and subsequently marks this with a warning message.
I just applied this technique in the way as it was proposed in the book "Head first design patterns" by the well-known Freeman-guys, Kathy Sierra & Bert Bates.
Besides this having also read a very ineresting ibm-article about this issue on http://www.ibm.com/developerworks/java/library/j-dcl.html, I am not sure any more if double-checked locking is an eligible and valid way to really provide thread safety ?
Kind regards,
Andy
|
SCJP, SCJD
|
 |
Roel De Nijs
Bartender
Joined: Jul 19, 2004
Posts: 4389
|
|
Hi Andy,
I created my singleton just like this:
As you see nothing fancy, just simple and easy.
Kind regards,
Roel
|
SCJA, SCJP (1.4 | 5.0 | 6.0), SCJD
http://www.javaroe.be/
|
 |
Andy Jung
Ranch Hand
Joined: Feb 07, 2010
Posts: 150
|
|
Hi Roel,
yes, of course you're right. This is the possibly simplest way to create a threadsafe singelton.
But what, if I want to create a singleton with a lazy loading behaviour?
The way you did it, is creating it eagerly, i.e. the constructor is called instantly when the class is loaded.
Since the singelton I use has a lot of work to accomplish when being created (reading and parsing the database
file for example), I want to have this done not when the server is started but rather when the singelton is first requested.
So, how can you create a threadsafe singleton with lazy instantiation behavior?
I am not sure, wether double checked locking is the correct answer?
The code, marked as not threadsafe by my IDE looks like the following:
Thanks,
Andy
|
 |
Roel De Nijs
Bartender
Joined: Jul 19, 2004
Posts: 4389
|
|
Hi Andy,
Maybe you have to implement the "initialization on demand holder idiom", which can be found here.
I'm wondering about how you will pass the path to database file to your singleton.
Kind regards,
Roel
|
 |
Andy Jung
Ranch Hand
Joined: Feb 07, 2010
Posts: 150
|
|
Hi Roel,
the requirement of my special assignment says, that the database file has to be located in the current working directory.
This is why I don't have to pass anything, just having to retrieve the path dynamically.
Thanks for the "initialization on demand holder idiom", this is really cool stuff !
The most amazing about this is, that this technique has lazy behaviour without the need to synchronize.
Besides, I detected the error in my solution:
I forgot to apply the keyword volatile on the instance variable:
My IDE goes fine with this now, however, the "initialization on demand holder idiom" seems to be far more effectively to me.
Kind regards,
Andy
|
 |
Roel De Nijs
Bartender
Joined: Jul 19, 2004
Posts: 4389
|
|
Andy Jung wrote:the requirement of my special assignment says, that the database file has to be located in the current working directory.
This is why I don't have to pass anything, just having to retrieve the path dynamically.
Are you sure about this? Because it's the very first time I hear about this requirement.
My assignment says:
Such configuration information must be stored in a file called suncertify.properties which must be located in the current working directory.
And that's a complete other story.
By the way, I would advice against the use of keyword "volatile".
Kind regards,
Roel
|
 |
Kai Witte
Ranch Hand
Joined: Jul 17, 2004
Posts: 354
|
|
|
The IBM article you mentioned is not up to date. With the implementation of JSR 133 in 1.5, double-checked locking can be used.
|
Kai Witte's business website Kai Witte's private homepage Mock exam / preparation kit reviews
|
 |
Andy Jung
Ranch Hand
Joined: Feb 07, 2010
Posts: 150
|
|
Hi Roel,
Roel De Nijs wrote:
Andy Jung wrote:the requirement of my special assignment says, that the database file has to be located in the current working directory.
This is why I don't have to pass anything, just having to retrieve the path dynamically.
Are you sure about this? Because it's the very first time I hear about this requirement.
No I'm not sure ;-), thanks for your hint ...
Roel De Nijs wrote:[
My assignment says:
Such configuration information must be stored in a file called suncertify.properties which must be located in the current working directory.
And that's a complete other story.
My assignment says the same ;-) ...
But anyway, does this matter? I mean, my singleton can access the property-file and retrieve the path to the database file, because it knows, that the property file has to be located in the current working directory.
This way I don't have to pass the file-path to the constructor of my DataFileAccess class (implemented as a singleton), or do I?
Kind regards,
Andy
|
 |
Roel De Nijs
Bartender
Joined: Jul 19, 2004
Posts: 4389
|
|
Hi Andy,
I faced the same problem as you: how do I pass the necessary information to my Data class? I just created an init-method in my own interface (extending sun's) which has a parameter to pass the database file location. Of course this method has to be invoked before any other method invocation on Data instance.
I never thought of your approach (just reading the properties file), because you know its location. But in my opinion it is not the best possible approach.
Kind regards,
Roel
|
 |
Andy Jung
Ranch Hand
Joined: Feb 07, 2010
Posts: 150
|
|
Hi Roel,
your solution sounds interesting. But how can you assure, that your method passing the vital information is called before any other methods ? There's no guarantee that Sun's automated Unit tests running against your Data-class conform to your intentions?
So, tell me, how did you encounter this problem?
Kind regards,
Andy
|
 |
Roel De Nijs
Bartender
Joined: Jul 19, 2004
Posts: 4389
|
|
Hi Andy,
I clearly javadoc'ed this requirement (and also explained in choices.txt). And an IllegalStateException is thrown when you try to invoke another method before the init-method.
Kind regards,
Roel
|
 |
Andy Jung
Ranch Hand
Joined: Feb 07, 2010
Posts: 150
|
|
Hi Roel,
ok, I understand.
But wasn't your approach actually very risky?
Just imagine what would have happened, if, before any human being or assessor had taken a look on your choices.txt or javadocs, an automated tool like JUnit tests ran against your implementation of Sun's provided DB interface?
Because of your runtime-exception thrown it might have resulted in an automated failure. The exam would have been assessed no further and you would have failed :-(.
Is this worth it?
So even if my approach is not the most elegant one and even not flexible to future changes of requirements, I think it is very reliable.
Kind regards,
Andy
|
 |
Roel De Nijs
Bartender
Joined: Jul 19, 2004
Posts: 4389
|
|
Hi Andy,
I don't want to scare you (or make you question your approach again), BUT I don't agree with
So even if my approach is not the most elegant one and even not flexible to future changes of requirements, I think it is very reliable.
You are using singleton design pattern, which requires your Data constructor to be private, so when the JUnit test case tries something likeI guess you'll see the problem, not reliable at all
My good buddy Roberto Perillo told me he also had a singleton design pattern and had besides the expected getInstance() also a getInstance(String dbLocation) variant. And he passed with that approach, so that was for me an assurance that singleton design pattern is allowed and that you won't automatically fail.
Kind regards,
Roel
|
 |
Andy Jung
Ranch Hand
Joined: Feb 07, 2010
Posts: 150
|
|
Hi Roel,
actually I didn't realize the Data-class as a singleton.
The Data class just references a DAO (= Data access object, conforming to the DAO design pattern).
This DAO itself is a facade (conforming to the facade design pattern) holding two singeltons:
an eagerly created singelton named LockManager responsible for logical record lockinga lazily created singelton named DataFileReader responsible for accessing the database file
So actually there's no risk with this approach, because the Data class has a normal constructor.
So, any further arguments versus my approach of retrieving the database file location dynamically in singelton DataFileReader ;-) ?
Kind Regards,
Andy
|
 |
Roel De Nijs
Bartender
Joined: Jul 19, 2004
Posts: 4389
|
|
Hi Andy,
My mistake. I was a bit to focused on my solution, so didn't think of the facade design pattern applied to the Data class. But you are right: no restrictions on Data class, so very reliable approach. Well done
If you think about high cohesion (reading properties file is not the task of your DataFileReader) I don't have any arguments about your approach.
Kind regards,
Roel
|
 |
Andy Jung
Ranch Hand
Joined: Feb 07, 2010
Posts: 150
|
|
Roel De Nijs wrote:
If you think about high cohesion (reading properties file is not the task of your DataFileReader) I don't have any arguments about your approach.
Yes, this is a flaw as I stated before. But I am a "Beckenrandschwimmer" (as a Dutch do you understand this German word ?), so I accept this design flaw in favor of a very risky but more flexible solution.
Kind regards,
Andy
|
 |
Roel De Nijs
Bartender
Joined: Jul 19, 2004
Posts: 4389
|
|
Hi Andy,
I'm a Dutch speaker from Belgium, but I don't know the word. Even my dictionary doesn't know it
I passed with my approach with a nice score and a whole lot others passed too with creating own interface, using singleton pattern for the data class (marking constructor private),... So I think if you have a similar approach it is not that risky...
Kind regards,
Roel
|
 |
Paul Clapham
Bartender
Joined: Oct 14, 2005
Posts: 16487
|
|
Andy Jung wrote:Hi Roel,
yes, of course you're right. This is the possibly simplest way to create a threadsafe singelton.
But what, if I want to create a singleton with a lazy loading behaviour?
The way you did it, is creating it eagerly, i.e. the constructor is called instantly when the class is loaded.
Since the singelton I use has a lot of work to accomplish when being created (reading and parsing the database
file for example), I want to have this done not when the server is started but rather when the singelton is first requested.
Perhaps I'm missing some background information here, but normally classes are not loaded until the first time they are requested. So normally, the behaviours you call "lazy" and "eager" in this context are identical.
But perhaps there's some reason why this class would be loaded when the server starts?
|
 |
Andy Jung
Ranch Hand
Joined: Feb 07, 2010
Posts: 150
|
|
Hi Roel,
Roel wrote:
I'm a Dutch speaker from Belgium, but I don't know the word. Even my dictionary doesn't know it
Roel
Well, it's actually a composed word consisting of three parts:
Beckenrandschwimmer = Becken + Rand + Schwimmer;
Becken = pool;
rand = edge;
Schwimmer = swimmer;
... actually it's a funny word for someone who always swims to the edge of the pool, because he fears that he might drown
Best regards,
Andy
|
 |
Andy Jung
Ranch Hand
Joined: Feb 07, 2010
Posts: 150
|
|
Paul Clapham wrote:
But perhaps there's some reason why this class would be loaded when the server starts?
|
 |
Andy Jung
Ranch Hand
Joined: Feb 07, 2010
Posts: 150
|
|
Hi Paul,
Paul Clapham wrote:
But perhaps there's some reason why this class would be loaded when the server starts?
As I said before, between the DB-interface and the DataFileAccess-class, there is a facade-class holding references to the logical LockManager and the DataFileAccess.
Maybe I'm missing some background, but I thought when declaring DataFileAccess as instance variable in the way:
the class loader begins loading the class in the VM.
In this context, eager and lazy-implementations behaves differently to me.
But maybe I didn't get the point?
Regards,
Andy
|
 |
Roel De Nijs
Bartender
Joined: Jul 19, 2004
Posts: 4389
|
|
Andy Jung wrote:it's actually a composed word consisting of three parts
I was able to recognize these 3 parts, but not give it a meaning which makes sense in the context you used it. I kept thinking about "someone living on the edge", but that's the complete opposite
Paul Clapham wrote:But perhaps there's some reason why this class would be loaded when the server starts?
Normally the server's sole purpose in this assignment is to expose the Data class (fat client) or some business layer (which refers to a Data instance, thin client). So when the server starts, the Data class should be initialized immediately, because it is quiet useless to have your server up and running if the database file doesn't exist or is empty or is not a database file (contains wrong magic cookie)
Kind regards,
Roel
|
 |
Andy Jung
Ranch Hand
Joined: Feb 07, 2010
Posts: 150
|
|
Roel De Nijs wrote:
Normally the server's sole purpose in this assignment is to expose the Data class (fat client) or some business layer (which refers to a Data instance, thin client). So when the server starts, the Data class should be initialized immediately, because it is quiet useless to have your server up and running if the database file doesn't exist or is empty or is not a database file (contains wrong magic cookie)
That's a good argument for creating an eager singleton rather than a lazy one.
Thanks Roel for your advice, I can use your arguments directly for my choices.txt !
Regards
Andy
|
 |
 |
|
|
subject: Double-checked locking and the Singleton pattern ?
|
|
|