1. ホーム
  2. java

[解決済み] BufferedInputStreamがフィールドを直接使用するのではなく、ローカル変数にコピーするのはなぜですか?

2022-10-25 04:16:28

質問

のソースコードを読むと java.io.BufferedInputStream.getInIfOpen() のソースコードを読むと、なぜこのようなコードが書かれているのか混乱します。

/**
 * Check to make sure that underlying input stream has not been
 * nulled out due to close; if not return it;
 */
private InputStream getInIfOpen() throws IOException {
    InputStream input = in;
    if (input == null)
        throw new IOException("Stream closed");
    return input;
}

なぜフィールド変数ではなくエイリアスを使うのでしょうか? in を直接使うのではなく、エイリアスを使うのはなぜですか?

/**
 * Check to make sure that underlying input stream has not been
 * nulled out due to close; if not return it;
 */
private InputStream getInIfOpen() throws IOException {
    if (in == null)
        throw new IOException("Stream closed");
    return in;
}

誰か合理的な説明をお願いします。

どのように解決するのですか?

このコードを文脈から見ると、その "alias" には良い説明がありません。これは単に冗長なコードか、コード スタイルが悪いだけです。

しかし、コンテキストは BufferedInputStream はサブクラス化できるクラスであり、マルチスレッドのコンテキストで動作する必要があるということです。

手がかりとなるのは in の中で宣言されている FilterInputStreamprotected volatile . ということは、サブクラスが手を伸ばして nullin . その可能性を考えると、quot;alias" は実際にはレースコンディションを防ぐためにあるのです。

alias" を使用しないコードを考えてみましょう。

private InputStream getInIfOpen() throws IOException {
    if (in == null)
        throw new IOException("Stream closed");
    return in;
}

  1. スレッドAの呼び出し getInIfOpen()
  2. スレッドAが評価する in == null を評価し、その結果 innull .
  3. スレッドBは nullin .
  4. スレッドAが実行されます。 return in . を実行し、その結果 null なぜなら avolatile .

alias"がこれを防ぎます。現在 in はスレッド A によって一度だけ読まれます。スレッド B が null を割り当てた後、スレッド A が in を実行した後では、それは問題ではありません。スレッド A は例外を投げるか、(保証された)非 NULL 値を返します。