Karthik
Karthik

Reputation: 477

Stuck updating a single variable updated by multiple threads

I have an app that uses multiple threads to write to a single variable "theVar" below. 99% of the times I have the correct data, but at times some data goes missing. I have been trying to solve this for almost a week now and I am really lost. It just happens all of a sudden and I lose data, a very serious issue. What am I doing wrong?

class Singleton {
    private volatile Singleton instance;
    private volatile String theVar = null;
    private final Object lock = new Object();

    public void setVar(String newVar) {
        synchronized (lock) {
            theVar = newVar;
        }
    }

    public String getVar() {
        synchronized (lock) {
            return theVar;
        }
    }

    public void appendVar(String text) {
        synchronized (lock) {
            theVar += text;
        }
    }

    protected Singleton() {
    }

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

        return instance;
    }
}

Upvotes: 1

Views: 862

Answers (2)

hagrawal7777
hagrawal7777

Reputation: 14658

Buddy, for creating Singleton my recommendation would be to use below approach which is 100% thread safe and no synchronization issue because it leverages Java's class loading mechanism.

Like this class Provider will be loaded only once (JVM will never load a class twice) when you getInstance() will be called first time by first thread and hence only one instance of Singleton class will exist.

Even if 2 threads will try to call getInstance() method at same time, but JVM will not load Provider two times, and since we are creating Singleton class instance as part of static initialization, which mean on class loading, so only one instance will exist.

In your case, probably 2 threads at very exact same time were causing some problem; give a try to this and I hope you should get 100% results. If not then please provide code of how you are running the same.

    public class Singleton {
        private Singleton() {
        }

        private volatile String theVar = null;

        public void setVar(String newVar) {
            synchronized (this) {
                theVar = newVar;
            }
        }

        public String getVar() {
            synchronized (this) {
                return theVar;
            }
        }

        public void appendVar(String text) {
            synchronized (this) {
                theVar += text;
            }
        }

        private static class Provider {
            static final Singleton INSTANCE = new Singleton();
        }

        public static Singleton getInstance() {
            return Provider.INSTANCE;
        }
    }

Upvotes: 2

Andreas
Andreas

Reputation: 5103

try something like this:

  public enum Singleton {
    INSTANCE;
    private volatile String theVar = null;


    public synchronized void setVar(String newVar) {
        theVar = newVar;
    }

    public String getVar() {
        return theVar;
    }

    public synchronized void appendVar(String text) {
        theVar += text;
    }
  }

Upvotes: 2

Related Questions