2

のようなクラス定義があるとしましょう

  public static class Bootstrapper {

    public static final Object DEFAULT_VALUE = getDefaultValue();

    private static Object getDefaultValue() {
      if (DEFAULT_VALUE == null) {
        return createValue(); // Not thread safe
      }
      return DEFAULT_VALUE;
    }
  }

メソッドはフィールドをcreateValue()参照せず、それ以外の場合はクラスのコンストラクターでのみ呼び出され、スレッドセーフではありません。DEFAULT_VALUEBootstrapper

上記のコードに (プログラミング スタイル以外に) 何か問題はありますか? クラスの初期化のルールを考えると、おそらくスレッドセーフは問題ではありませんが、プログラマーが知っておくべき重要なことはありますか?

4

2 に答える 2

3

Augusto が説明しているように、あなたのコードはスレッドセーフです。しかし、それはかなり複雑です。単純にこれを行うと、機能的に同等で、わずかに効率的で、はるかに明確になります。

   public static class Bootstrapper {    
     private static final Object DEFAULT_VALUE = createValue();

     public static Object getDefaultValue() {
       return DEFAULT_VALUE;
     }
   }

編集:フィールドがパブリックで、ゲッターがプライベートであることに気付きました。それはおそらく逆のはずです。

于 2015-03-04T21:51:35.950 に答える
2

これはスレッドの観点から安全です。クラスのロードはスレッド セーフであり、その値が設定されるため (したがってgetDefaultValue()) は、クラスがロードされた後、クラスのロード コードを離れる前に呼び出されます。

上記の元の質問に関する PNS コメントに答えるには、クラスが 2 つの異なるクラスローダーによってロードされている場合、synchronizedキーワード ongetDefaultValue()を使用するとクラスがロックされるため、とにかく問題が発生します...そして 2 つのクラスがあるため、それぞれが完全に独立してください。これは、Java 言語仕様のセクション4.3.4 参照型が同じ場合(JLS 8 の場合) で読むことができます。

于 2015-03-04T21:43:48.917 に答える