Java Singleton and Synchronization

Java Singleton and Synchronization

Yes, it is necessary. There are several methods you can use to achieve thread safety with lazy initialization:

Draconian synchronization:

private static YourObject instance;

public static synchronized YourObject getInstance() {
if (instance == null) {
instance = new YourObject();
}
return instance;
}

This solution requires that every thread be synchronized when in reality only the first few need to be.

Double check synchronization:

private static final Object lock = new Object();
private static volatile YourObject instance;

public static YourObject getInstance() {
YourObject r = instance;
if (r == null) {
synchronized (lock) { // While we were waiting for the lock, another
r = instance; // thread may have instantiated the object.
if (r == null) {
r = new YourObject();
instance = r;
}
}
}
return r;
}

This solution ensures that only the first few threads that try to acquire your singleton have to go through the process of acquiring the lock.

Initialization on Demand:

private static class InstanceHolder {
private static final YourObject instance = new YourObject();
}

public static YourObject getInstance() {
return InstanceHolder.instance;
}

This solution takes advantage of the Java memory model's guarantees about class initialization to ensure thread safety. Each class can only be loaded once, and it will only be loaded when it is needed. That means that the first time getInstance is called, InstanceHolder will be loaded and instance will be created, and since this is controlled by ClassLoaders, no additional synchronization is necessary.

Java synchronize in singleton pattern

It's just like any other class. It may or may not need further synchronization.

Consider the following example:

public class Singleton {

private Singleton() {}

public synchronized static Singleton getInstance() { ... }

private int counter = 0;

public void addToCounter(int val) {
counter += val;
}
}

If the class is to be used from multiple threads, addToCounter() has a race condition. One way to fix that is by making addToCounter() synchronized:

  public synchronized void addToCounter(int val) {
count += val;
}

There are other ways to fix the race condition, for example by using AtomicInteger:

  private final AtomicInteger counter = new AtomicInteger(0);

public void addToCounter(int val) {
counter.addAndGet(val);
}

Here, we've fixed the race condition without using synchronized.

SingleTon class is not synchronized and returning multiple instances

You need to change the following:

1) Make your default constructor private. As written, it is package-private and can be called by other classes in the same package.

private SingleTon() {
}

Once you have done this, your SingleTonDemo class will no longer be able to call the constructor and will be forced to use the getInstance() method. Currently, each call to the constructor is creating a new instance.

2) Synchronize the entire getInstance() method. As written, 2 separate threads can get a null value for singleTonInstance, and thus each thread would create a new instance.

    public static SingleTon getInstance() {

2a) An alternate approach to ensuring there is only one instance of the class is to use static initialization. In the declaration of the static variable, you create the object:

private static SingleTon singleTonInstance = new SingleTon();

The JVM will ensure that this is called only one. That also improves your getInstance method as you would change it to:

public static SingleTon getInstance() {
return singleTonInstance;
}

The advantage of this approach is that not only is the getInstance method simpler, it also does not incur the overhead of being synchronized.

Synchronized block in Singleton Pattern (Java)

If it wasn't synchronized, you could indeed have 2 threads create 2 objects.

  • T1: checks if instance is null => yes! => continues to next line
  • T2: checks if instance is null => yes! => continues to next line
  • T1: creates object
  • T2: creates object

While using synchronized, only 1 thread can enter the synchronized blocked at a time.

  • T1: checks if instance is null => yes! => continues to next line
  • T1: creates object
  • T2: checks if instance is null => no! => skips block

Edit:

It is worth noting that the null check inside of the synchronized
block is actually very important - otherwise it would be possible to
create 2 objects as well. – Amongalen (in comments)

Another way to achieve a Singleton pattern is the following. Only use this pattern if creating the object isn't a big problem to do as soon as the application starts:

public final class Singleton {

private static Singleton instance = new Singleton();

private Singleton() {}

public static Singleton getInstance() {
return instance;
}
}

How to synchronize two methods in a singleton pattern

Note: The post below was written in the perspective of both users using the same credentials (hidden from them) to connect to the database. If users employ different credentials, the idea of a singleton db object is purposeless, each user should have their own connection object, and of course then connection details are passed on from the user to the Db via whatever represents the user in the program (here the thread instances apparently).

The main issue in the implementation you provided is that the getinstance method requires its caller to know the connection details, or assume that the connection has already been done. But neither threads could nor should know in advance if the Db has been opened already -- and design wise it's a mistake to hand them the responsibility of explicitely opening it. These threads are work threads, they shouldn't be concerned about Db configuration details.

The only sane way to handle this situation is to have these configuration parameters held by the Db object directly, or better yet another object in charge of providing it (it's the factory pattern).

However, if you want first your code to work with minimal changes, get rid of the parameter less getinstance method, have any thread requiring the Db object to use the remaining variant of that method, passing along the correct parameters, and change it to return the instance if it exists, or create it otherwise, without raising an exception. I believe that it's what @Dima has been trying to explain in his answer.

Is necessary synchronize thread safe singleton's methods

Just because getInstance() is thread safe, that does not mean any other methods of the class are thread safe. Multiple threads can still perform operations on the singleton object simultaneously.

You should synchronize a private final class member object inside the setX function. Do not synchronize this and do not synchronize the entire method. Synchronizing this synchronizes the object and if other code also synchronized the object returned by getInstance(), you could have yourself a deadlock. Putting the synchronized keyword before methods means that only one synchronized method of the synchronized methods in your class can be executed by a thread on an instance at any given time. It can also give the impression to clients/consumers of the class that the class is thread safe even though it may not be.

A good approach to writing a singleton is to use an enum as that guarantees there will only ever be one instance of it. However, the member functions of the enum will still need to be synchronized if you want it to be thread safe. See page 311 of Effective Java for an example of this: http://uet.vnu.edu.vn/~chauttm/e-books/java/Effective.Java.2nd.Edition.May.2008.3000th.Release.pdf

When using the singleton design pattern, do other methods need to use synchronized keyword to ensure thread safety?

First, a Singleton pattern is best implemented as Enum in Java
Second, each email manipulation function (clear, Recycle, delete) should be synchronized to ensure thread safety (the link is about an Enum, but the same holds about each and every Sinlgeton implementation):

public synchronized void RecycleEmail(Email email)

proper usage of synchronized singleton?

Double-checked locking has been proven to be incorrect and flawed (as least in Java). Do a search or look at Wikipedia's entry for the exact reason.

First and foremost is program correctness. If your code is not thread-safe (in a multi-threaded environment) then it's broken. Correctness comes first before performance optimization.

To be correct you'll have to synchronize the whole getInstance method

public static synchronized Singleton getInstance() {
if (instance==null) ...
}

or statically initialize it

private static final Singleton INSTANCE = new Singleton();


Related Topics



Leave a reply



Submit