当我从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;
}
有人可以给出合理的解释吗?
解决方案如下:
如果您是从上下文中看这段代码,那么对于“别名”就没有很好的解释。它仅仅是冗余代码或不良的代码样式。
但是上下文是BufferedInputStream
是可以子类化的类,并且它需要在多线程上下文中工作。
线索是in
中声明的FilterInputStream
是protected volatile
。这意味着子类有可能进入并为null
分配in
。考虑到这种可能性,实际上会使用“别名”来防止出现竞争状况。
考虑不带“别名”的代码
private InputStream getInIfOpen() throws IOException {
if (in == null)
throw new IOException("Stream closed");
return in;
}
getInIfOpen()
in == null
并发现in
不是null
。 null
分配给in
。 return in
。由于null
是a
,因此返回volatile
。 “别名”可以防止这种情况。现在
in
只能由线程A读取一次。如果线程B在线程A具有
null
之后分配了
in
,则没有关系。线程A将抛出异常或返回(保证的)非空值。