阻止更新由多个线程更新的单个变量

时间:2015-06-08 21:58:19

标签: java multithreading

我有一个使用多个线程写入单个变量的应用程序" theVar"下面。 99%的时间我拥有正确的数据,但有时会丢失一些数据。我一直试图解决这个问题差不多一个星期了,我真的迷路了。它只是突然发生,我丢失数据,这是一个非常严重的问题。我做错了什么?

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;
    }
}

2 个答案:

答案 0 :(得分:2)

尝试这样的事情:

  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;
    }
  }

答案 1 :(得分:2)

Buddy,为了创建Singleton我的建议是使用以下方法,它是100%线程安全且没有同步问题,因为它利用了Java的类加载机制。

就像这个类Provider只会被加载一次(JVM永远不会加载一个类两次)当第一次调用第一次调用getInstance()时将存在一个Singleton类的实例。

即使2个线程同时尝试调用getInstance()方法,但JVM也不会加载Provider两次,因为我们正在创建Singleton类实例作为静态的一部分初始化,这意味着在类加载时,因此只存在一个实例。

在你的情况下,在同一时间可能有两个线程导致一些问题;试试这个,我希望你能得到100%的结果。如果没有,那么请提供您如何运行相同的代码。

    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;
        }
    }