0

メンバー フィールドとして既に保持されている静的な揮発性変数へのローカル参照を作成する目的または値は何ですか。このコードは、java.util.Scanner JDK 6b14 hereからのものです。

class Scanner {
    private static volatile Pattern linePattern;
    ...
    private static Pattern linePattern() {
        Pattern lp = linePattern;
        if (lp == null)
            linePattern = lp = Pattern.compile("...");
        return lp;
    }
    ...
}

Java チュートリアル: 「読み取りと書き込みは、volatile と宣言されたすべての変数 (long 変数と double 変数を含む) に対してアトミックです... volatile 変数への書き込みは、同じ変数の後続の読み取りとの先行発生関係を確立します。」

これは、Pattern オブジェクトへの参照の読み取りが、変更されたために途中で失敗しないことを意味します。volatile キーワードは、これらの種類のアクセスを正確に保護することになっているため、重複するローカル変数は、有効な値が返されることを保証するものではありません。

また、中間ローカル変数を必要とせずに、メンバー フィールドで遅延初期化を実行できます。

if (linePattern == null) linePattern = Pattern.compile("...");

hereおよびhereに見られるように、バイトコードの最適化のようです。ローカル変数を使用すると、バイトコードが小さくなり (命令が少なくなります)、実際の値へのアクセスが少なくなります (これは、高価な揮発性読み取りです)。しかし、彼らは最終的な変数の最適化をそれと一緒に使用していないので、私はこの結論を引き出すことに懐疑的です.

4

4 に答える 4

2

遅延初期化、つまり、本当に必要になるまで作業を遅らせます。

于 2013-02-02T21:04:05.850 に答える
1

チェックとリターンの間に静的変数がNULLに設定されている場合でも、戻り値がNULLではないことが保証されます。

同時に、それは同期されていない怠惰な初期化であり、必要に応じて再初期化されます;)。

于 2013-02-02T21:13:32.363 に答える
1

これは物事を「スピードアップ」します。volatile変数へのアクセスは高価です。スタック変数に代入して代わりにアクセスすることで、このオーバーヘッドを回避できます。

于 2013-02-02T22:50:13.267 に答える
0

volatileフィールドの場合、linePattern異なる行間で が変わる場合があります。ローカル変数への参照をコピーすると、一貫性のない状態になることはありません。たとえば、あなたが書いた場合

 if (linePattern == null)
    linePattern = Pattern.compile("...");

thenの実行中に null でなくlinePatternなった可能性があります。Pattern.compile

于 2013-02-02T21:05:04.150 に答える