25

実際のJava並行性という本から:

オブジェクトを安全に発行するには、オブジェクトへの参照とオブジェクトの状態の両方を同時に他のスレッドから見えるようにする必要があります。適切に構築されたオブジェクトは、次の方法で安全に公開できます。

  • 静的初期化子からのオブジェクト参照の初期化

  • それへの参照を volatile フィールドまたは AtomicReference に格納する

  • それへの参照を適切に構築されたオブジェクトの final フィールドに格納する


  • それへの参照を、ロックによって適切に保護されたフィールドに格納します。

私の質問は次のとおりです。

  1. 箇条書き 2 と 3 の違いは何ですか? オブジェクトの安全な公開に関するvolatileアプローチとアプローチの違いに興味があります。final
  2. ポイント 3 で適切に構築されたオブジェクトのfinal フィールドとはどういう意味ですか? 箇条書きのポイントを開始する前に、著者は適切に構築されたオブジェクトについて話していることをすでに述べました (これは、thisエスケープへの参照を許可していないと思います)。しかし、なぜ彼らは適切に構築されたオブジェクトについて言及したのでしょうか?
4

2 に答える 2

18

箇条書き 2 と 3 の違いは何ですか?

  • volatile基本的に、そのフィールドへの書き込みは他のスレッドから見えることを意味します。したがって、フィールドを volatile: として宣言するprivate volatile SomeType field;と、コンストラクターがその field: に書き込む場合field = new SomeType();、この割り当ては、後で読み取りを試みる他のスレッドによって可視になることが保証されますfield
  • final非常に似たセマンティクスを持っています: final フィールドがある場合:private final SomeType field;そのフィールドへの書き込み (宣言またはコンストラクターのいずれか):オブジェクトが適切に処理されていれば、field = new SomeType();リオーダーされず、他のスレッドから見えるようになるという保証があります。公開されthisています(つまり、たとえばのエスケープはありません)。

明らかに、主な違いは、フィールドが final の場合、一度しか割り当てることができないことです。

ポイント 3 で適切に構築されたオブジェクトの final フィールドとはどういう意味ですか?

たとえば、thisコンストラクターからエスケープすると、最終的なセマンティクスによって提供される保証が失われます。監視スレッドは、フィールドをデフォルト値 (オブジェクトの場合は null) で見る可能性があります。オブジェクトが適切に構築されている場合、これは発生しません。


考案された例:

class SomeClass{
    private final SomeType field;

    SomeClass() {
        new Thread(new Runnable() {
            public void run() {
                SomeType copy = field; //copy could be null
                copy.doSomething(); //could throw NullPointerException
            }
        }).start();
        field = new SomeType();
    }
}
于 2013-02-09T19:09:41.137 に答える
2

パブリッシングと の効果に違いはありませんが、volatileコンストラクfinalターfinalで一度しか設定できないため、読み取った内容は決して変更されません。

適切に構築されたオブジェクトは実際にあなたが参照しているものであり、this参照がコンストラクターをエスケープせず、それが使用されているスレッドに安全な方法で公開されているオブジェクトであると私は信じています.

于 2013-02-09T19:10:31.467 に答える