1

このコードは、ダブルチェック ロックのアンチパターンを示すために使用されます。

@NotThreadSafe
public class DoubleCheckedLocking {
    private static Resource resource;

    public static Resource getInstance() {
        if (resource == null) {
            synchronized (DoubleCheckedLocking.class) {
                if (resource == null)
                    resource = new Resource();
            }
        }
        return resource;
    }
}

次のように変更して、この問題を回避できますか。

@NotThreadSafe
public class DoubleCheckedLocking {
    private static Resource resource;

    public static Resource getInstance() {
        if (resource == null) {
            synchronized (DoubleCheckedLocking.class) {
                if (resource == null){
                    Resource r=new Resource();
                    resource = r;
                }
            }
        }
        return resource;
    }
}

私の知る限りでは、

Resource r=new Resource();
resource = r;

そのコンパイラは、そのための事前発生関係を提供する必要があります。

4

3 に答える 3

4

私の知る限り、(JDK5以降で)機能するダブルチェックロックパターンの唯一の既知の実装は、「volatile」キーワードを使用します。揮発性物質を使用したダブルチェックロックの修正を参照してください。

于 2012-09-15T15:54:40.290 に答える
2
public static Resource getInstance() {
    if (resource == null) {
        synchronized (DoubleCheckedLocking.class) {
            if (resource == null){
                Resource r=new Resource();
                resource = r;
            }
        }
    }
    return resource;
}

スレッド間の適切な可視性を保証する唯一のことは、同期を介して(、、 ...を介して)同期との関係を作成することですsynchronizedvolatile

synchronizes-with関係がない場合、他のスレッドからの変更を確認するためにスレッドは必要ありません。

この場合、スレッドはを作成し、Resourceそれへの参照をに格納することができますresource。次に、2番目のスレッドが入る可能性があります。getInstance()を参照してくださいresource != null。この2番目のスレッドは、最初のスレッドと同期されresourceていないため、の構造のすべての効果を確認できるとは限りません。

于 2012-09-15T16:35:51.340 に答える
2

コンパイラは以下を最適化できます。

Resource r=new Resource();
resource = r;

resource=new Resource();

したがって、あなたの調整は効果がありません。

于 2012-09-15T18:35:54.700 に答える