16

JMMの因果関係は、最も混乱しているようです。私はJMM因果関係についていくつかの質問をしており、並行プログラムでの行動を許可しています。Javaメモリモデルでこの動作が許可されるのはなぜですか?

私が理解しているように、現在のJMMでは因果律ループを常に禁止しています。 (私は右だ?)

さて、JSR-133文書、ページ24、図16のとおり、私たちは例があります。

最初x = y = 0

スレッド1:

r3 = x; 
if (r3 == 0) 
    x = 42; 
r1 = x; 
y = r1; 

スレッド2:

r2 = y; 
x = r2; 

直感的にはr1 = r2 = r3 = 42と思われます。しかし、それは可能な限り言及されているだけでなく、JMMで「許可」されています。可能性を

、私は理解できない文書からの説明は次のとおりです。

コンパイラこれまでxに割り当てられた値のみがコンパイラができた、それから、 0および42であることを決定することができます我々が xの書き込みを実行したか、またはxを読んだだけで42の値を見たかのいずれかで、 を実行したと推測されます。どちらの場合でも、読み取りには合法ですの値を参照してください。その後、r1 = xr1 = 42に変更することができます。これにより、y = r1y = 42に変換され、先に実行され、結果として の問題が発生します。この場合、yへの書き込みは、最初に にコミットされます。

私の質問は、どのようなコンパイラの最適化は本当ですか? (私はコンパイラには無知です。)42は条件付きでしか書かれていないので、if文が満たされたときに、コンパイラはxの書き込みにどうすればいいですか?今残された原因と結果の区別がないので

は第二に、コンパイラは、この投機的な最適化を行い、最終的にr3 = 42を行い、その後y = 42と を犯したとしても、それは、因果関係ループの違反ではないのですか?

実際、同じ文書(15ページ、図7)には、同様の原因ループが許容できないと言われる例があります。

この実行命令はJMMではどのように合法ですか?

答えて

6

としては、説明、これまでxに書き込まれた値のみが0および42スレッド1:

r3 = x; // here we read either 0 or 42 
if (r3 == 0) 
    x = 42; 
// at this point x is definitely 42 
r1 = x; 

したがってJITコンパイラはr1 = 42としてr1 = xを書き換え、さらにy = 42ができます。要点は、スレッド1は常に、無条件にを書く42からyです。 r3変数は実際には冗長であり、マシンコードから完全に削除することができます。したがって、この例のコードは、xからyまでの因果律的な矢印の出現を示していますが、詳細な分析によれば、実際には因果関係はありません。驚くべき結果は、yへの書き込みを早期にコミットできることです。

最適化に関する一般的な注意事項:メインメモリからの読み取りに伴うパフォーマンスの低下に精通しています。そのため、可能であればJITコンパイラはそれを拒否することに賛成しており、この例ではyに何を書き込むかを知るために実際にはxを読む必要はないことが分かります。

表記上の一般的な注:r1r2r3ローカル変数(それらがスタックまたはCPUレジスタであってもよい)です。 x,y共有変数(これらはメインメモリにあります)です。これを考慮することなく、例は意味をなさないでしょう。

1

javacがコードを有意義に最適化しないことは何も価値がありません。 JITはコードを最適化しますが、コードを並べ替えることについてはかなり控えめです。 CPUは実行を並べ替えることができますが、これはかなり小さなものになります。

命令レベルの最適化を行わないようCPUに強制するのは、かなり高価です。それは10倍以上遅くすることができます。 AFAIK、Javaの設計者は、ほとんどのCPU上で効率的に動作するために最低限必要な保証を指定したいと考えました。

3

コンパイラは、いくつかの分析および最適化を実行し、スレッド1のコードを以下で終了することができる:シングルスレッド実行について

y=42; // step 1 
r3=x; // step 2 
x=42; // step 3 

は、このコードは、元のコードと等価であるので、法的です。次に、スレッド1のコードがステップ1とステップ2の間で実行された場合(これも可能です)、r3にも42が割り当てられます。

このコードサンプルの全体的な考え方は、適切な同期の必要性を示すことです。

+0

@アレクセイその一部を説明します。しかし、コンパイラは 'r3 = 42'の代わりに' r3 = 0'を作るべきではありませんか?あるいは、彼らは単に「可能性」を示しているだけです! – gaganbm

+2

コンパイラは 'r3 = 42'を作成しません。' r3 = x'をそのまま残します。コンパイラの最適化は必ずしも最大深度まで実行されるわけではありません。最適化が正当性に違反する可能性が最小限であれば、それは放棄されます。与えられたコードでは、そのような状況はありませんが、他のコードがあれば現れる​​ことがあります。また、コンパイラは 'r3 = 0'が' r3 = x'と同じ価格であると判断できます。 –

関連する問題