Win a copy of Java Challengers this week in the Java in General forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Paul Clapham
  • Ron McLeod
  • paul wheaton
  • Devaka Cooray
Sheriffs:
  • Jeanne Boyarsky
  • Tim Cooke
  • Liutauras Vilda
Saloon Keepers:
  • Tim Moores
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Piet Souris
Bartenders:
  • salvin francis
  • Mikalai Zaikin
  • Himai Minh

Semantics of Singleton instantiation

 
Ranch Hand
Posts: 88
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Good Evening Everyone,

I'm having trouble understanding the semantics of Singleton creation.
While following a tutorial on the net, I could immediately see that I could create more than one object of a singleton class,
So I tested it out and indeed I can. Am I missing something ?

Here's the code and output of my test program:






output

 
Marshal
Posts: 72657
317
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
A singleton can be altered to have a certain, fixed, number of instances.
Please tell us where that code comes from; it is incorrect. It is thread unsafe. If you have a race condition and two calls are made to that factory method simultaneously, it is possible to create two instances without knowing about it.
Afraid I haven't got enough time to explain more just now.
 
Saloon Keeper
Posts: 12893
280
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Your output doesn't prove that two objects are created. Only one object is created.
 
Mohammed Azeem
Ranch Hand
Posts: 88
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello after some thought I think I have an understanding.

But first I think the original code wasn't perhaps the best for learning about Singletons - that code came from baeldung.com but in fairness the tutorial went on to talk about threads.
So I'm using this code to share my understanding: courtesy of www.tutorialspoint.com "Java - How to Use Singleton class"







The key to this is that:
*  the class defines a private field and assigns an instance of Singleton to it


* so whenever I call the same object is assigned to the reference variables (which can have different names).

I received your responses as I was typing mine - so thank you to both of you.
 
Saloon Keeper
Posts: 8094
71
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
So far this is the safest implementation of a singleton that I've seen. It's a little problematic if the constructor has a lot of overhead or makes use of external resourses but I don't have an answer for that at the moment. For most cases, this approach should suffice.
 
Mohammed Azeem
Ranch Hand
Posts: 88
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thankyou.
I see the crucial access modifier 'final' in:

 
Marshal
Posts: 26531
81
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
All of that was probably useful in learning something, but for singleton objects:



Guaranteed to be thread-safe creation, guaranteed to create exactly one object, much less code to be concerned about. There aren't going to be many reasons why you shouldn't use an enum singleton, so in practice you should always use one when you need a singleton.
 
Stephan van Hulst
Saloon Keeper
Posts: 12893
280
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mohammed Azeem wrote:"Java - How to Use Singleton class"


There is only one answer to this question.

"You don't."
 
Saloon Keeper
Posts: 23540
161
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paul Clapham wrote:There aren't going to be many reasons why you shouldn't use an enum singleton, so in practice you should always use one when you need a singleton.



Well, because it's more than a bit kludgy.

As for the more traditional constructs show here, first I'd like to complain that "INSTANCE" is poor use of capitaliization. All-caps constants are generally atomic-ish types like manifest primiitives or Strings.

I'd also not that the form under construction isn't so much a "singleton" per se as it is a bean with integrated singleton factory. Which isn't something I deal with much because my beans are usually manufactured by the Spring Framework and the default semantics for the Spring BeanFactory return singletons without requiring any special characteristics in the bean itself.
 
Bartender
Posts: 2854
150
Google Web Toolkit Eclipse IDE Java
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Although I don't advocate singletons, here's an implementation I recall from a long time back:
Thread-safe and Lazy loaded. There's no synchronization logic required above since it's the JVM that does the loading and initialization on demand for the class above.
 
Tim Holloway
Saloon Keeper
Posts: 23540
161
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm not sure that's as lazy as you think it is, but it's an improvement.

Enough talk about thread safety, Am I being blind again or did no one actually write any thread-safe code besides Salvin?



The apparent redundancies are based on the idea that an object reference fetch is very low overhead, but synchronization is not. AND - very importantly, that a reference fetch is atomic. The redundant test for null is becaise there is a window between testing and instantiation so if two requests hit simultaneously, they'll queue up and the second hit on the instance will see that the first hit had already instantiated it.

You can of course, simplify this logic by synchronizing every request, but as I said, I'm looking for high efficiency here. I recommend benchmarking, since a good spin lock may not have enough overhead to make this necessary. But that would also depend on the underlying hardware and its implementation.
 
Tim Holloway
Saloon Keeper
Posts: 23540
161
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Also, it's critical that "instance" is declared volatile!
 
Stephan van Hulst
Saloon Keeper
Posts: 12893
280
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:I'm not sure that's as lazy as you think it is


How is it not?

Tim Holloway wrote:Also, it's critical that "instance" is declared volatile!


Why is it critical?
 
Tim Holloway
Saloon Keeper
Posts: 23540
161
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
A) it would depend on how aggressively the class itself is loaded, and I don't know offhand if there are codified rules for that.

B) If "instance" is not defined as volatile, code optimization says that the second null test can save a fetch and assume it's still null.

Just being within a synchronized clause isn't enough, since synchonization here was done on the class not on the instance (which would fail if the instance was null).
 
salvin francis
Bartender
Posts: 2854
150
Google Web Toolkit Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The code I posted is lazy loaded. It will be instantiated the moment the jvm loads this class. Yes, this could differ as per jvm implementations, but the code should hold up to being thread safe.
The main question is .. Do we need singletons ? (Now that's an interesting conversation)  
 
Tim Holloway
Saloon Keeper
Posts: 23540
161
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I never argued thread safety, just immediacy of intantiation. Although now that I think if it, the classloader would have to synchronize itself, since multiple threads could be using a single classpath. So in theory, I've got you beat on performance.

I did think of a few ways for classes to be loaded by stealth, though. For example, if a class was subject to code-weaving by an Aspect-Oriented Programming (AOP) process. You might not be able to know or predict when the process would kick in.

The exact timing of the singleton instantiation and how knowable it needs to be really depends on how much work the singleton's constructor and factory have to do to construct that single instance. And if it's significant, there are probably problems here quite aside from singularity. I suppose if you had a LOT of class-based singletons and there was some event that triggered a massive class inrush, that might be a concern.

Now, are singletons necessary? Well, I'd argue better a singleton than a static-only class, based on experience. The BeanFactory used by Spring Data is a singleton, although technically all that needs to be single is the factory method itself (which can be static). The various DAOs and other useful objects that I have Spring serve up are singletons, and there's be no advantage otherwise (in fact, it could risk database corruption). But those are functional singletons, and not enforced singletons.

So I suppose it depends on how you define "need".
 
Rancher
Posts: 3850
50
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Salvin's code relies on the holder class idiom, which relies on the fact that there is, in fact, a precise guarantee in the JLS about when class initialization occurs.  "Loading" is a more general term - loading occurs "sometime before"... but initialization, including initializing static fields and running static initializers, is guaranteed to happen just before the first use of a class.  In the case of the nested class MySingleton.Loader, the first use will be the first time getInstance() is called, and it needs to access the field Loader.INSTANCE.
 
Tim Holloway
Saloon Keeper
Posts: 23540
161
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The critical difference is that loading is harder to predict. I can load a class via Class.forName() for example without actually explicitly accessing properties or methods.

AOP was one example where loading might occur long before you realize it, but I'm sure other cases can be found.
 
Mike Simmons
Rancher
Posts: 3850
50
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You can use Class.forName() to force initialization, that's true.  But note that Class.forName("MySingleton") is not enough to trigger instantiation of the singleton - you would need to use Class.forName("MySingleton$Loader").  Yes, it's possible, but it tends not to happen by accident.

It's true that if you use AOP there may well be some sneaky or hard-to-anticipate stuff going on, and maybe your "lazy" initialization will not be as lazy as you thought.  More generally, the more complex stuff you do, the more unforseen side effects can occur.  But, you can take steps that help minimize the chances of that happening.  The static holder idiom is one such example - it's pretty lazy, most of the time.  But if you poke it enough, you can find ways to make it less lazy.  Which is usually what you want, for lazy loading.  
 
Stephan van Hulst
Saloon Keeper
Posts: 12893
280
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:Just being within a synchronized clause isn't enough, since synchonization here was done on the class not on the instance (which would fail if the instance was null).


Doesn't matter. As long as all threads agree on the object that's being synchronized on (in this case it's an instance of Class), Java's memory model guarantees that thread B will NEVER read the instance field to be null on line 4 when thread A has already entered the synchronized block before. The synchronized keyword makes stronger guarantees than the volatile keyword.
 
Stephan van Hulst
Saloon Keeper
Posts: 12893
280
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:But, you can take steps that help minimize the chances of that happening.  The static holder idiom is one such example - it's pretty lazy, most of the time.  But if you poke it enough, you can find ways to make it less lazy.  Which is usually what you want, for lazy loading.  


It's also just an interesting curiosity.

If you only need one instance of an object, just create one instance. And if it's expensive to construct, you're breaking yet another good programming practice: don't do heavy lifting in constructors.

Don't rely on this dumb pattern to do your work for you. Its only appeal is that it's easy for beginners to understand.
 
Mike Simmons
Rancher
Posts: 3850
50
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:

Tim Holloway wrote:Just being within a synchronized clause isn't enough, since synchonization here was done on the class not on the instance (which would fail if the instance was null).


Doesn't matter. As long as all threads agree on the object that's being synchronized on (in this case it's an instance of Class), Java's memory model guarantees that thread B will NEVER read the instance field to be null on line 4 when thread A has already entered the synchronized block before. The synchronized keyword makes stronger guarantees than the volatile keyword.



I think the use of volatile is important here, but Tim's stated reason is off.  As Stephan says, the issue is not whether it's synchronized on class or instance.  And it's not any issue with the second null check - since the second null check is guarded by synchronization.  The problem is that, without volatile, the first null check has no guarantees with respect to what happens inside the synchronized block.  In particular, with legal code reorderings, the reference to the instance field may be assigned, before the singleton's initialization completes.  That won't cause any problems within the sync block, but it could definitely be problematic for other concurrently running code that bypasses the sync block.  A field of the singleton could be observed as null, even if it was assigned in the constructor to be something else.  

The fix of using volatile means that any code outside the sync block that tries to use the instance reference will be subject to memory barriers similar to synchronization - either they will see a fully-initialized object, or they will see null.  Not some in-between state.

Stephan van Hulst wrote:If you only need one instance of an object, just create one instance. And if it's expensive to construct, you're breaking yet another good programming practice: don't do heavy lifting in constructors.



Stephan van Hulst wrote:Don't rely on this dumb pattern to do your work for you. Its only appeal is that it's easy for beginners to understand.


Heh.  Well, the initial idea was easy for beginners to understand.  The convolutions people have done in the name of optimization, well, those aren't easy for anyone to understand, I think.  That's the problem.  Although a lot of that is the general difficulty of writing thread-safe code in Java, in general.  That was initially sold as "easy" in Java ("just use synchronized!"), and many subtle bugs were created in the name of optimization, by people who thought they understood all the things that could happen.  The singleton is just a greatly overused example of that.

From my perspective, the main problem with the singleton pattern is that people don't really question why they want only one instance, and how important that is, or why.  Often, they need only one instance in production.  Fine.  But they also need to be able to test their code, and so they will also discover they need to mock out some behavior... which means they discover that they actually need to replace that one true singleton instance with a mock object.  And then, it's not really a singleton at all anymore.  Which is usually fine - but raises the question, why did people spend all that effort to allow only one instance?  When it wasn't actually a problem?

However, despite the fact that I don't much like singletons either, I still encounter them in code written by others. And I personally don't have the time or authority to get rid of them every time I encounter them.  Some are coded acceptably well, and some are not.  It's helpful to understand the pattern well enough to tell which implementations are more problematic, and which are less troubling... and choose my battles accordingly.
 
Stephan van Hulst
Saloon Keeper
Posts: 12893
280
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote: In particular, with legal code reorderings, the reference to the instance field may be assigned, before the singleton's initialization completes.


You're completely right. Sorry Tim, I was only concerned with the state of the instance field, as not the internal state of the actual singleton object.
 
Tim Holloway
Saloon Keeper
Posts: 23540
161
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:
From my perspective, the main problem with the singleton pattern is that people don't really question why they want only one instance, and how important that is, or why.  Often, they need only one instance in production.  Fine.  But they also need to be able to test their code, and so they will also discover they need to mock out some behavior... which means they discover that they actually need to replace that one true singleton instance with a mock object.  And then, it's not really a singleton at all anymore.  Which is usually fine - but raises the question, why did people spend all that effort to allow only one instance?  When it wasn't actually a problem?



Replaceability does not affect singularity. If I reference a singleton via Interface and all implementors of that Interface likewise implement singularity, then it's still singular. And if they don't, then the test is arguably invalid and may break things that weren't broken in production when an actual Singleton was used.

I may have my semantics too much wrapped up in C here, but - barring guarantees in the JVM implementation spec, I'd expect synchronization to restrict access to synchronized code, not necessarily expanded out to class properties. For me, it's the code's responsibility to guard the properties. If the JVM extends semantics to automatically and invisibly guard properties as well, well and good, but I prefer the less optimistic view, lest I develop bad habits elsewhere.

Am I wrong that you cannot declare a property as synchronized, only code? I haven't see it done, and again, being a pessimist, just because you use a property as a synchronization doesn't mean that a bad actor cannot modify the synchronized object. In fact, unconstrained semantics says that the following horror might be perfectly legal:

All synchronized code (syncCode) would work as expected as long as the nonsysc code was not invoked. The nonsync code, however, could totally mess that up. PROVIDING. That the synchronized code modified locks on the object value and not the object name (defined storage slot). And the reason I'd worry about that is I'm pretty sure I've gotten NullPointerExceptions when syncing on an object whose value is null. Id est, Locks are for Honest People.

On the other hand, I'm reasonably certain that fetching an object value is an atomic operation. Meaning that if all you want to do is fetch, you don't actually need synchronization. You need synchronization to avoid concurrent modification issues, and you might guard your fetches to be absolutely certain where in the chronology the value changes, but in many cases that's not that actually important. Hence my non-synchronized test for null before committing to synchronization. The initial fetch, being non-synchronized, is fast and I can safely return it if non-null. However, if it detects a null value, then I immediately synchronize. I'm then immediately re-fetching, since that unsynchronized interval between the fetch and starting sync is a possible exposure and I don't want that. As I said, I use volatile so that the fetch will physically be done and I don't have to worry about optimizers re-using the possibly stale results of the previous fetch. I DO NOT assume that the optimizer will consider entering synchronization to be sufficient to dump internal optimization state as there's no absolute reason that it should (only design decisions, if any).

I'm also skeptical of excessively-wide protection being guaranteed on a class, since if that was really true, you'd simply mark the class itself as synchronized. There'd be no point in synchronizing code or code blocks, since that model would be forced to always synchronize whether synchronized code was being invoked or note. For its own protection.

So, in short, I act as though synchronization is solely done on code, locking the code on an object instance (even if it's the instance of java.lang.Class). If Java's semantics extend to synchronization on the objects themselves or the totality of the class, that's just more safety (although likely more overhead). I'm not assuming it, however, since, as I said, that's not a Universal Truth and Java isn't the only language I do multi-threading in.
 
reply
    Bookmark Topic Watch Topic
  • New Topic