5

コンストラクターの実行後に確立されたメモリ フェンスについての私の理解を誰かが検証してくれませんか。たとえば、Stock というクラスがあるとします。

public final class Stock{

       private final String ticker;
       private double qty;
       private double price;

       public Stock ( String ticker, double qty, double price ){
              this.ticker  = ticker;
              this.qty     = qty;
              this.price   = price;

              //I am assuming a memory fence gets inserted here.
       }


       public final void updateQty( double qty ){
           this.qty = qty;
       }


       public final void updatePrice( double price ){
           this.price = price;
       }

}

さらに、コンストラクターが Thread1 によって実行され、Thread2によって(常に Thread2 によって)何度も呼び出されるとしますupdateQty()updatePrice()

私の主張は、Thread1 がオブジェクトを作成した後、オブジェクトの「可視性」が jvm 内の他のすべてのスレッドで確立されるということです。また、2 つの可変変数は Thread2 によってのみ変更されるため、ロックは必要ありません。私は正しいですか?

4

2 に答える 2

5

私の主張は、Thread1 がオブジェクトを作成した後、オブジェクトの「可視性」が jvm 内の他のすべてのスレッドで確立されるということです。

これは正しくありません。暗黙のコンストラクターメモリバリア/フェンスがないため、コンストラクターの周りの命令の並べ替えがこのような問題になります。Stockオブジェクトを構築したスレッド以外の別のスレッドでオブジェクトを使用する場合はsynchronize、更新メソッドを呼び出す前にオブジェクトを使用する必要があります。

また、2 つの可変変数は Thread2 によってのみ変更されるため、ロックは必要ありません。

オブジェクトを最初に同期した後は、他のスレッドで変更されたフィールドを確認したい場合を除き、追加Thread2のロックは必要ありません。オブジェクトの変更中に複数のスレッドがオブジェクトから読み取っている場合、すべてのスレッドは、同期によって、またはフィールドを変更済みフィールドにすることによって、メモリバリアを越える必要があります。StockThread2volatile

これは、コンストラクター操作の並べ替えメモリの可視性の両方に関係しています。コンストラクターの並べ替えに関する落とし穴の詳細については、この回答を参照してください。

これはオブジェクトの安全な公開ですか?

于 2012-10-10T22:53:04.930 に答える
1

残念だけど違う。コンストラクタは(ほとんど)Javaメモリモデルの通常のメソッドに似ています。

それは悪いことですが、それはプログラマーに際限のない混乱を引き起こしました。

于 2012-10-10T22:58:04.433 に答える