1. ホーム
  2. java

[解決済み] Java シングルトンと同期

2022-07-18 22:49:04

質問

シングルトンとマルチスレッドに関する私の疑問を明らかにしてください。

  • マルチスレッド環境で、Java で Singleton を実装する最良の方法は何でしょうか? 環境において、シングルトンを実装する最良の方法は何ですか?
  • 複数のスレッドが getInstance() メソッドに同時にアクセスしようとするとどうなりますか?
  • シングルトンの getInstance() synchronized ?
  • シングルトンクラスを使用する場合、同期は本当に必要なのでしょうか?

どのように解決するのですか?

はい、必要です。遅延初期化でスレッドセーフを実現するために、いくつかの方法があります。

ドラコニアン同期。

private static YourObject instance;

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

この解決策では すべての を同期させる必要がありますが、実際には最初の数個だけが同期させる必要があります。

同期のダブルチェック :

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

この解決策は、シングルトンを取得しようとする最初の数スレッドだけが、ロックを取得するプロセスを経る必要があることを保証します。

オンデマンド初期化 :

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

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

このソリューションは、スレッドセーフを確保するために、クラスの初期化に関するJavaのメモリモデルの保証を利用します。各クラスは一度だけロードすることができ、必要なときだけロードされます。つまり、最初の getInstance が呼び出されたときに InstanceHolder がロードされ instance が作成され、これは ClassLoader によって制御されるので、追加の同期は必要ありません。