6

Double-checked locking and the Singleton patternの記事を読んでいて、二重チェックのロックがどのように壊れているか、およびスタック オーバーフローに関するいくつかの関連する質問を読んでいました。

このパターン/イディオムを何回も問題なく使用しました。私は Java 5 を使用して以来、これが Java 5 メモリー・モデルで修正されたのではないかと最初に考えました。ただし、記事には次のように書かれています。

この記事では、Java 5.0 用に改訂される前の Java メモリ モデルについて言及しています。メモリの順序付けに関するステートメントは、もはや正しくない可能性があります。ただし、ダブルチェック ロックのイディオムは、新しいメモリ モデルではまだ壊れています

これは本当の問題ですか? もしそうなら、どのような状況下で?

4

3 に答える 3

3

巧妙に見えるが壊れているダブルチェックロックに関するシングルトンの例を示す

同期ブロックを開始すると、最新のデータが表示されることが保証されますが、並べ替えが保証されるわけではありません。同期ブロック内にいない限り、データの一貫したビューは期待できません。同期セクション内で行われた変数の変更が他のスレッドに表示されることは保証されません。同期ブロックに入るスレッドだけが、変更を確認できることが保証されます。これが、ダブル チェック ロックが壊れている理由です。リーダー側で同期されていません。読み取りスレッドは、シングルトンが null ではないことを確認できますが、シングルトン データが完全に初期化されていない (表示されていない) 可能性があります

一方、順序付けは、順序付けを保証する volatile によって提供されます。たとえば、volatileシングルトン静的フィールドへの書き込みは、揮発性静的フィールドへの書き込みの前にシングルトン オブジェクトへの書き込みが終了することを保証します。2 つのオブジェクトのシングルトンの作成は妨げられません。これは synchronize によって提供されます。クラス final 静的フィールドは揮発性である必要はありません。Java では、JVM がこの問題を処理します。

詳細は次の場所にあります。

于 2010-08-18T20:09:07.860 に答える
2

自分のアプリケーションが実際に二重チェックのロック障害によってヒットしたことを確認するのは難しいでしょう。実際、このイディオムを使用する多くのアプリケーションでは、さまざまな理由で問題が発生することはありません。

ただし、それを使用する必要があるという意味ではありません。定量化できない失敗の可能性があるという事実だけで、特に安全な代替手段があるため、二重チェックのロックを使用しないように説得するのに十分なはずです。

あなたは幸運だった。

于 2010-03-20T06:13:06.627 に答える
2

壊れたダブルチェック イディオムを使用するアプリケーションがありましたが、非常に長い間完全に機能していました。実際、このイディオムで問題を経験したことはありません。もちろん気にせず直しました。

この理由の 1 つは、最終的に現実の世界でスレッドの可視性が達成されるためだと思います。そして一度達成すると、それはとどまります。そのため、問題が発生したかどうかを検出することは非常に困難です。

hashCode()実装はStringこの事実に部分的に依存していると思います...スレッドはキャッシュを見ない間にhashCodeを計算しますが、最終的には見始めます。一方、計算の重複は、 CPU時間の浪費を意味し、揮発性セマンティクスのメモリ効果を回避する利点は、この無駄な労力に勝ります (少なくとも、そのように実装したのはそのためだと思います)。有効な使用法のイディオムは (実際の String.hashCode() 実装) です。

/** Cache the hash code for the string */
private int hash; // Defaults to 0

public int hashCode() {
    int h = hash;
    if (h == 0) {
        int off = offset;
        char val[] = value;
        int len = count;

        for (int i = 0; i < len; i++) {
            h = 31*h + val[off++];
        }
        hash = h;
    }
    return h;
 }

明らかに、それを使用する前に多くのことを考え、測定する必要があります。

于 2010-03-20T06:22:02.570 に答える