Java以单例模式同步

Kla*_*Nji 8 java singleton synchronization

是否需要将synchronize关键字应用于实现单例模式的类的每个方法?

public class Singleton {

  private Singleton(){}

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

        return instance;
    }

  public void DoA(){
  }
}
Run Code Online (Sandbox Code Playgroud)

由于Singletons不公开公共构造函数并且getInstance()方法是同步的,因此不需要同步方法DoA和Singleton类公开的任何其他公共方法.

这个推理是否正确?

NPE*_*NPE 19

它就像任何其他类一样.它可能需要或可能不需要进一步同步.

请考虑以下示例:

public class Singleton {

  private Singleton() {}

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

  private int counter = 0;

  public void addToCounter(int val) {
    counter += val;
  }
}
Run Code Online (Sandbox Code Playgroud)

如果要从多个线程使用该类,addToCounter()则具有竞争条件.解决这个问题的一种方法是addToCounter()同步:

  public synchronized void addToCounter(int val) {
    count += val;
  }
Run Code Online (Sandbox Code Playgroud)

还有其他方法可以修复竞争条件,例如使用AtomicInteger:

  private final AtomicInteger counter = new AtomicInteger(0);

  public void addToCounter(int val) {
    counter.addAndGet(val);
  }
Run Code Online (Sandbox Code Playgroud)

在这里,我们已经修复了比赛条件而没有使用synchronized.


Del*_*ima 10

好吧,Singleton类的目的是它最多只有一个实例,所有Threads都可以访问同一个对象.

如果您不同步该getInstance方法,则可能发生以下情况

Thread1进入 getInstance()

Thread2进入 getInstance()

Thread1评估instance == nulltrue

Thread2评估instance == nulltrue

Thread1分配instance并返回

Thread2 重新分配instance = new Singleton()并返回.

现在线程都有一个Singleton类的不同实例,这是该模式应该阻止的.

同步可防止两个线程同时访问同一代码块.因此,在实例化单例类时,多线程环境中需要同步.

现在假设多个线程将同时尝试访问Singletons方法,同样可能需要同步这些方法.特别是如果他们改变数据而不是只读它,这是真的.

  • 我认为这个问题是指 Singleton 实例的公共方法,而不是静态的“getInstance”。 (2认同)