What do you do for Singleton?

ajoo 2002-06-20 02:36:00
I see many programmers do singleton like:
class Singleton implements I{
static Singleton _inst = null;
static I getInstance(){if(_inst==null)_inst = new Singleton();return _inst}
}

Well, it works.
But, think hard. why wouldn't you do
class Singleton implements I{
static final Singleton _inst=new Singleton();
static I getInstance(){return _inst;}
}
?
Much simpler, right?

Many programmers would say: "the first one is lazy initialization. So should be better."

Really? by using the first one, what do you save? a Singleton object, right?

But how big is that? From my experience, a singleton is normally quite small. For a small object with 10-20 bytes, is it worthy the extra code "if(......)"?
the extra code will not use memory space anyway?
and it makes your code unnecessarily more complicated.

does it worth the extra runtime overhead to check the reference everytime the getInstance() is called?

Also, programmer often ignore the thread-safety of the first approach.

What if there are threads calling getInstance() concurrently? Do you need to place "synchronized" on your getInstance()?
And if you place "synchronized", you may also feel uncomfortable because even for non-concurrent usage of your Singleton, you are also paying the locking overhead for each call against getInstance(). Painful!

Of course, for big object, the lazy intialization is certainly useful. But, there's still another approach you may want to consider if the memory space for this big object is really something.

think about this: if every user of the singleton has finished using this singleton, do I still need to hold this object? Can I reclaim the memory space for it?

Then, you may want to use WeakReference to further optimize it.

for example:

class Singleton implements I{
static WeakReference _inst = null;
static I getInstance()
{
if(_inst==null || _inst.get()==null)
_inst = new WeakReference(new Singleton());
return (I)_inst.get();
}
}

It works?
Well, looks like. But no!
(I give this wrong demo to show that sometimes introducing more code is probably introducing more chances to get bug.)

You may just return "null" sometimes. This is because of the WeakReference! It does not guarantee to hold the new Singleton instance for you.

So, a possible version would be:
class Singleton implements I{
static WeakReference _inst = null;

static synchronized I getInstance()
{
I ret;
if(_inst==null){
ret = new Singleton();
_inst = new WeakReference(ret);
}
else
{
ret = (I)_inst.get();
if(ret == null){
ret = new Singleton();
_inst = new WeakReference(ret);
}
}
return ret;
}
}
quite something to do!
...全文
56 34 打赏 收藏 转发到动态 举报
写回复
用AI写文章
34 条回复
切换为时间正序
请发表友善的回复…
发表回复
abcabcabc___ 2002-07-01
  • 打赏
  • 举报
回复
no, jls didnt say that way, for example, if you have a global varible x , which is used to flag certain condition or holding something, then currently, your only hope is x is no bigger than 32 bits. because volatile doesnt work properly.

BTW, immutable string can be changed make the whole immutable a joke.
ajoo 2002-07-01
  • 打赏
  • 举报
回复
ok. thank you for the link!
design patterns can easily go too abstract and phylosophical.
yakuu 2002-07-01
  • 打赏
  • 举报
回复
ok, our discussion should be over.
continued topic is far off.
but can we talk about the design patterns.
i can use 200 each topic.^_^
ajoo 2002-07-01
  • 打赏
  • 举报
回复
he he. imutable only when you do it immutably.

for example,

msg = new String(...);

see? msg's still mutable.

and the problem is because of the mutable assignment.
abcabcabc___ 2002-06-30
  • 打赏
  • 举报
回复
the worest thing is , it breaks and you dont know. the error may happen once in 10 days or produce a result 1% larger than the original. those errors are very very hard to discover. i have heard that a bank emploree put all the interest below 1 cent to his own account when develope the system and got several handred thousand in 2 years and no auditing found it. how much checking normal program can enjoy?

yakuu 2002-06-30
  • 打赏
  • 举报
回复
the volatile keyword in Java is certainly not worthless or taboo. In fact, it is sometimes crucial that you do use it.

Alas, the only truly useful answer is "don't use it". At least, don't rely on it for anything...
Basically, the language and VM specifications don't really make it clear/precise/etc. what should/shouldn't really be done in the presence of volatile and so many implementations of the JVM don't do anything if volatile is specified. Note that there are some folks actively working to solve this in time for the next release.

so, we still rely upon the double check code.
yakuu 2002-06-30
  • 打赏
  • 举报
回复
alas, yes, make sure the object is big enough.

mm...but how big? ^_^
ajoo 2002-06-30
  • 打赏
  • 举报
回复
at least the object size has to be big enough (not just 10 bytes, 20 bytes) to justify the runtime overhead and code complexity of lazy init or double check.
yakuu 2002-06-30
  • 打赏
  • 举报
回复
how to use it depend on yourself .

both ok. i think.

^_^
ajoo 2002-06-30
  • 打赏
  • 举报
回复
concurrent programming IS tricky by itself.
The problem with double check was not ever promised by the jls that it will work.
So, if any program using double check failed, it's the code's bug,(at most you can blame the jls is not clear or not good) just as many other bugs in concurrent code. They are normally hard to find in nature.
and how many programs are using double check? don't think it's quite useful in real. As the article said, "static init" is neat and good enough.


"volatile" may be used to fix the problem in double check in the future. But before the new jls is made and all the current impl supports that, we as programmers should just wisely avoid double check.

Again, strongly recommend using "static init". Easy! most efficient! robust!
ajoo 2002-06-30
  • 打赏
  • 举报
回复
it works only in the new proposal of "volatile" semantics.
Now, volatile does not help at all.


But, don't think many Java code is "bound to" break.
ajoo 2002-06-29
  • 打赏
  • 举报
回复
Shocked!
thought the double check works!

anyway, it proves my claim: never bother complex code if not necessary.


Thank you yakuu! It has been extremely helpful! Otherwise, I might use the double check in my future projects.
:)
yakuu 2002-06-29
  • 打赏
  • 举报
回复
the difference is keyword:volatile

^_^
yakuu 2002-06-29
  • 打赏
  • 举报
回复
the old code:

public class JGKSingleton {
private static JGKSingleton instance_;
private static Object syncObject_;
public static JGKSingleton getInstance() {
if (instance_ == null) {
synchronized(syncObject_) {
if (instance_ == null) {
instance_ = new JGKSingleton();
}
}
}
return instance_;
}
}

the new code:

public class JGKSingleton {
private static volatile JGKSingleton instance_;
private static Object syncObject_;
public static JGKSingleton getInstance() {
if (instance_ == null) {
synchronized(syncObject_) {
if (instance_ == null) {
instance_ = new JGKSingleton();
}
}
}
return instance_;
}
}
abcabcabc___ 2002-06-29
  • 打赏
  • 举报
回复
didnt know there's such a nasty problem in java's design.
anyone knows if the memory model fixed?
If not, then java on mp machines are broken. with immutable can be changed, your program are bond to break.
yakuu 2002-06-28
  • 打赏
  • 举报
回复
i think there is a good article:
http://www.javaworld.com/javaworld/jw-01-2001/jw-0112-singleton.html

let's read it.^_^
yakuu 2002-06-28
  • 打赏
  • 举报
回复
mm, first, the singleton code is like that:

package com.jgk.patterns.singleton;
public class JGKSingleton {
/* Here is the instance of the Singleton */
private static JGKSingleton instance_;
/* Need the following object to synchronize */
/* a block */
private static Object syncObject_;
/* Prevent direct access to the constructor
private JGKSingleton() {
super();
}
public static JGKSingleton getInstance() {
/* in a non-thread-safe version of a Singleton */
/* the following line could be executed, and the */
/* thread could be immediately swapped out */
if (instance_ == null) {
synchronized(syncObject_) {
if (instance_ == null) {
instance_ = new JGKSingleton();
}
}
}
return instance_;
}
}

in my mind, it's work fine.
hehe, but i suspect it since i saw this article:
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

maybe it's true.
i'll check it.
yakuu 2002-06-28
  • 打赏
  • 举报
回复
at first, the code of above is wrong.
code like that:
public static Singleton getInstance() {
/* in a non-thread-safe version of a Singleton */
/* the following line could be executed, and the */
/* thread could be immediately swapped out */
if (instance_ == null) {
synchronized(this) {
if (instance_ == null) {
instance_ = new Singleton();
}
}
}
return instance_;
}

in my mind, i think it's work fine.hehe, but i have seen an article:
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

take a look at it. maybe it's true.
ajoo 2002-06-28
  • 打赏
  • 举报
回复
but when the space used by your "if(...)lock()if(...)....." is more than the memory used by the singleton object, what do you use?

and, the complex code at least needs a "if(...)" everytime, slower.
yakuu 2002-06-28
  • 打赏
  • 举报
回复
i have seen these codes in a paper.
mm, talking about design patterns, but it's purpose is compare with c++.
i think both ok if we don't care about the memory.
but my prefer the complex codes.^_^
加载更多回复(14)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧