2017-06-13 3 views
1

ストアストアバリアをコンストラクタに配置する必要がありますか?コンストラクターにStoreStoreバリアーが必要ですか?

ここは例です。最初にglobal_f = f = r = 0とします。 1つのスレッドAがオブジェクトを作成し、フィールドに割り当て、グローバル変数に代入:

class Foo { 
    int x; 
    void Foo(int x) { 
     this.x = x; 
    } 
} 

f = new Foo(42); 
global_f = f; 

別のスレッドBは、グローバル変数から参照を取得し、そのフィールドを読み取ります。スレッドBはスレッドBからオブジェクト参照を読み出す

r = global_f.x; 

仮定すると実行が、どのような値は、それがrXから読み取ることができますか?常に42かどうか?

私はC++ Javaの動作に興味があります。 rは、メモリモデルを理解するためには42であることが保証されていません。

オブジェクトのフィールドが適切に初期化されるように、一般的なコンストラクタの最後にストアストアバリアを置くことができます。これは、C++とJavaの両方の落とし穴のようです。少なくともJavaの場合、最終フィールドにはすべて問題ありませんか?これは実際にはそれほど重要ではありません。なぜなら、少なくともx86とAMD64では、ストア・ストア・バリアがNOPであるからです。しかし、ARMやPOWERなどの他のアーキテクチャではそうではありません。

+1

C++のみ:自動的にメモリバリアが追加されることはありません。プログラマの問題です。次のガイドラインが適用されます。_「ルールを使用するための唯一の支払い」_およびマルチスレッドは、コンパイラによる静的解析には複雑すぎます(コンパイラは各コンパイル単位を個別に認識します)。 –

+0

質問したい言語を絞り込む必要があります。 JavaとC++は異なるメモリモデルと言語セマンティクスを持っています。一つは、クラスはC++の値であり、参照はありません。もう1つはJavaの「volatile」がC++のものと大きく違っている –

+0

なぜここでコンストラクタを選ぶべきかわかりません。状況は、 'x'を設定する他のメソッド呼び出しと同じです。 – EJP

答えて

1

Javaの場合、はというフィールドを宣言しない限り、が42になるという保証はありません。


オブジェクトのフィールドが正しく初期化されていることを確認するために、我々は一般的には、コンストラクタの最後にストアストア障壁を置くことができます。これは、C++とJavaの両方の落とし穴のようです。

これはコメントではありません。しかし、逆の議論は、すべてのコンストラクタの終わりに暗黙のバリアを置くことは、様々な場合において不必要なパフォーマンス・ヒットをもたらすことである。例えばfxへのアクセスが同期方式でガードされているマルチスレッドコードを

  • を公表していないマルチスレッドコードのシングルスレッドコード、
  • ため

    JavaとC++のメモリモデルは、単純さとパフォーマンスの考慮点の間で妥協点があります。単純すぎる場合(つまり、落とし穴を設計するなど)、マルチスレッドコードを使用しても、人々が望む/必要とするスピードアップは得られません。

  • 関連する問題