/ / Javaはシングルトンパターンで同期する - java、sync、singleton

Javaはシングルトンパターンで同期する - java、sync、singleton

このようなシングルトンパターンを実装するクラスの各メソッドには、synchronizedキーワードを適用する必要がありますか?

public class Singleton {

private Singleton(){}

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

return instance;
}

public void DoA(){
}
}

シングルトンは一般公開しないのでコンストラクタとgetInstance()メソッドが同期されている場合、メソッドDoAとSingletonクラスによって公開される他のパブリックメソッドを同期させる必要はありません。

この推論は正しいのでしょうか?

回答:

回答№1の17

他のクラスと同じように、それ以上の同期は必要ないかもしれません。

次の例を考えてみましょう。

public class Singleton {

private Singleton() {}

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

private int counter = 0;

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

クラスを複数のスレッドから使​​用する場合は、 addToCounter() 競合状態にあるこれを修正する1つの方法は、 addToCounter() 同期:

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

競合状態を修正するには、他の方法があります。 AtomicInteger

  private final AtomicInteger counter = new AtomicInteger(0);

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

ここでは、使用せずに競合状態を修正しました synchronized.


回答№2については9

Singletonクラスの目的は、たかだか1つのインスタンスがあり、すべてのスレッドが同じオブジェクトにアクセスできることです。

あなたが getInstance 方法は次のことが起こり得る

スレッド1が入ります getInstance()

スレッド2が入る getInstance()

スレッド1が評価する instance == nulltrue

スレッド2の評価 instance == nulltrue

スレッド1の割り当て instance 返品

スレッド2 割り当て instance = new Singleton() 返されます。

現在、スレッドは両方とも、このパターンによって防止されていたはずのものであるSingletonクラスの違いインスタンスを持っています。

同期化は、両方のスレッドが同じコードブロックに同時にアクセスできるようにします。したがって、シングルトンクラスをインスタンス化するときは、マルチスレッド環境で同期が必要です。

複数のスレッドが同時にSingletonsメソッドにアクセスするには、それらのメソッドでも同期が必要になることがあります。特に、データを読み取るだけでなくデータを変更する場合は、これが当てはまります。


回答№3の場合は1

Singletonを使用する正しい(実際にベストな)方法

private static singleton getInstance() {
if (minstance == null) {
synchronized (singleton.class) {
if (minstance == null) {
minstance = new singleton();
}
}
}
return minstance;
}

回答№4の場合は1

遅延初期化とスレッドセーフソリューション:

public class Singleton {

public static class SingletonHolder {
public static final Singleton HOLDER_INSTANCE = new Singleton();
}

public static Singleton getInstance() {
return SingletonHolder.HOLDER_INSTANCE;
}
}