Best way to synchronize in a Singleton
I have this classimport java.util.ArrayList;
import java.util.List;
publicclass SynchIssues
{
private List values =new ArrayList();
privatestaticfinal SynchIssues singleton =new SynchIssues();
publicstatic SynchIssues getInstance()
{
return singleton;
}
publicvoid addValue(String value)
{
synchronized(singleton)
{
values.add(value);
}
}
public String getValue(int i)
{
synchronized (singleton)
{
return (String) values.get(i);
}
}
}
And i synchronize on the singleton itself , but some collegue uses a different approach
import java.util.ArrayList;
import java.util.List;
publicclass SynchIssues2
{
private List values =new ArrayList();
privatestaticfinal SynchIssues2 singleton =new SynchIssues2();
publicstatic SynchIssues2 getInstance()
{
return singleton;
}
publicsynchronizedvoid addValue(String value)
{
values.add(value);
}
publicsynchronized String getValue(int i)
{
return (String) values.get(i);
}
}
He uses synchronize on the methods in stead of the SIngleton.
What approach is best ?
Are both approaches thread safe ?
Do teh different approaches risk deadlocking when different thread will be accessing the classes ?
[3304 byte] By [
pgeuensa] at [2007-10-2 9:57:50]

AFAIK, that's exactly the sameI'll give a check to see if there's a difference in bytecodes produced ;-)
kk thanks in advance ! not the bytecode expert myself
I ran into a third way of implementing this
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
public class SynchIssues3
{
private List values = Collections.synchronizedList(new ArrayList());
private static final SynchIssues3 singleton = new SynchIssues3();
public static SynchIssues3 getInstance()
{
return singleton;
}
public void addValue(String value)
{
values.add(value);
}
public String getValue(int i)
{
return (String) values.get(i);
}
}
Would this be similar too ?
yeah bytecode is different, but that's quite normal ;-)bytecode is even different when you replace synchronized(singleton) by synchronized(this), actuallynote that your co-worker's solution produces a shorter .class file... (not that it really matters but...)
> kk thanks in advance ! not the bytecode expert
> myself
I'm not either, just comparing files in an hexadecimal editor ;-)
>
> I ran into a third way of implementing this
>
> > import java.util.ArrayList;
> import java.util.List;
> import java.util.Collections;
>
> public class SynchIssues3
> {
> private List values =
> = Collections.synchronizedList(new ArrayList());
>
> private static final SynchIssues3 singleton = new
> ew SynchIssues3();
>
>public static SynchIssues3 getInstance()
>{
>return singleton;
>}
>
>public void addValue(String value)
>{
>values.add(value);
>}
>
>public String getValue(int i)
>{
>return (String) values.get(i);
>}
> }
>
>
>
> Would this be similar too ?
not quite sure about this one... I'm not a race-condition expert either... :(
size doesnt matter indeed Just need the most thread safe
> size doesnt matter indeed > ;-)
in a word: don't.google on double checked locking. it's broken.%
What do you need to do exactly? What does "the most thread-safe" mean?
If I read correctly your code samples, the fact that the "shared object" is a singleton is not relevant. Your point seems to be more about a generic issue of "synchronizing access to a shared collection".
Without resorting to bytecode examination, it seems your 3 code samples look equivalent as far as individual add() and get() operations are concerned: each operation is atomic, and only one thread is actually reading/modifying the collection at a given time. In this regard each of these operations can be told "thread-safe".
However it gives absolutely no guarantee about several operations executed in sequence : two threads executing such a sequence would probably see their get() and add() interleaved. This may or may not cause a problem depending on your application (what you do about the data in the collection, and in particular how you react to reaching the end of the list).
If you want this kind of guarantee of per-sequence atomicity (a sequence of, e.g., get() is executed without any other thread modifying the collection in between), you have to make sure each client synchronizes on the collection (or on the singleton, if it's the only wrapper) around the whole block of the sequence:
SynchIssueX singleton = SynchIssueX.getInstance();
// make sure no other thread may read any value before I've added them all:
synchronized (singleton) {
singleton.add(value1);
singleton.add(value2);
singleton.add(value3);
}
> in a word: don't.> > google on double checked locking. it's broken.> > %Where's the double-cheked locking in this thread? Did I miss it?
nope, i went back and re-read the code. knee jerk reaction. sorry.%
>What do you need to do exactly? What does "the most thread-safe" mean?
I just wonder if there is a difference or lurking flaw in the different ways of synchronizing the atomic operations
> the fact that the "shared object" is a singleton is not relevant.
Correct
>It seems your 3 code samples look equivalent
I was thinking the same just wondered if i missed some detail
>f you want this kind of guarantee of per-sequence atomicity
Good point , the collection will be filled with several items all at once so i need to be carefull with that too.
The first approach is not good.The 2nd approach is the best.See http://www-128.ibm.com/developerworks/java/library/j-dcl.html for an excelent and complete explanation.
> The first approach is not good.
> The 2nd approach is the best.
>
> See
> http://www-128.ibm.com/developerworks/java/library/j-d
> cl.html for an excelent and complete explanation.
1. This is an old thread.
2. The above suggestion that the first is "not good" is wrong.
3. The link has nothing to do with the several options that are being discussed.