为什么BufferedInputStream将字段复制到局部变量而不是直接使用该字段 [英] Why does BufferedInputStream copy a field to a local variable rather than use the field directly

查看:139
本文介绍了为什么BufferedInputStream将字段复制到局部变量而不是直接使用该字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我从 java.io.BufferedInputStream.getInIfOpen()中读取源代码时,我很困惑为什么它编写这样的代码:

When I read the source code from java.io.BufferedInputStream.getInIfOpen(), I am confused about why it wrote code like this:

/**
 * 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;
}

为什么使用别名而不是使用字段变量中直接如下所示:

Why is it using the alias instead of using the field variable in directly like below:

/**
 * 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;
}

有人可以给出合理的解释吗?

Can someone give a reasonable explanation?

推荐答案

如果你看看这个代码脱离了上下文,那么别名没有很好的解释。它只是冗余代码或糟糕的代码风格。

If you look at this code out of context there is no good explanation for that "alias". It is simply redundant code or poor code style.

但上下文是 BufferedInputStream 是一个类可以是子类化,并且它需要在多线程上下文中工作。

But the context is that BufferedInputStream is a class that can be subclassed, and that it needs to work in a multi-threaded context.

线索是中的被声明in FilterInputStream protected volatile 。这意味着子类可能会进入并在中将 null 分配给。鉴于这种可能性,别名实际上是为了防止竞争条件。

The clue is that in is declared in FilterInputStream is protected volatile. That means that there is a chance that a subclass could reach in and assign null to in. Given that possibility, the "alias" is actually there to prevent a race condition.

考虑没有别名的代码

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




  1. 线程A调用 getInIfOpen()

  2. 线程A在== null 中计算并看到 in 不是 null

  3. 线程B指定 null 中的$ c>到

  4. 线程A在中执行返回。返回 null 因为 a volatile

  1. Thread A calls getInIfOpen()
  2. Thread A evaluates in == null and sees that in is not null.
  3. Thread B assigns null to in.
  4. Thread A executes return in. Which returns null because a is a volatile.

别名阻止了这一点。现在中的只被线程A读取一次。如果线程B在线程A null >在中没关系。线程A将抛出异常或返回(保证)非空值。

The "alias" prevents this. Now in is read just once by thread A. If thread B assigns null after thread A has in it doesn't matter. Thread A will either throw an exception or return a (guaranteed) non-null value.

这篇关于为什么BufferedInputStream将字段复制到局部变量而不是直接使用该字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆