0

以下の A fix that doesn't work のコード スニペットを理解できませんでした。(同じページに続く説明を読みました)。

2 つの同期ブロックがある場合、この DCL バージョンはどのように壊れていますか? または、Java5以降は適用されませんか?

// (Still) Broken multithreaded version
// "Double-Checked Locking" idiom
class Foo { 
  private Helper helper = null;
  public Helper getHelper() {
    if (helper == null) {
      Helper h;
      synchronized(this) {
        h = helper;
        if (h == null) 
            synchronized (this) {
              h = new Helper();
            } // release inner synchronization lock
        helper = h;
        } 
      }    
    return helper;
    }
  // other functions and members...
  }
4

1 に答える 1

3

helper非 null と見なされるスレッドが、 によって行われたすべての書き込みを認識できるという保証はありませんnew Helper();。したがって、破損したバージョンのシングルトンにアクセスできます。完了にそれが見えることを保証するためにhelper、非と見なされるスレッドに何かが必要です。非揮発性変数への変更を観察しても、そのような関係は確立されません。そのスレッドが行うのはそれだけです。nullh = new Helper();

少し単純化しすぎると、Java のメモリ可視性モデルの仕組みは、2 つのスレッドがそれぞれ、2 つのスレッドによって実行される 2 つの操作の間に「前に発生する」/「後に発生する」関係を確立する何かを行うことです。これには、同期ブロック内の操作や揮発性変数へのアクセスが含まれます。

しかし、上記のコードを使用すると、スレッドはそうでhelperはないことを確認しnull、 によって作成されたオブジェクトにアクセスできますnew Helper()。変数にアクセスする必要volatileも、同期ブロックに入る必要もありません。したがって、 によって行われた変更を確実に確認するために必要な「後に発生する」関係を確立できる可能性があるものは何もありませんnew Helper()

于 2015-11-20T08:05:02.247 に答える