在java.util.Scanner
的源代码中,我发现了这些静态实用程序方法:
private static Pattern separatorPattern() {
Pattern sp = separatorPattern;
if (sp == null)
separatorPattern = sp = Pattern.compile(LINE_SEPARATOR_PATTERN);
return sp;
}
private static Pattern linePattern() {
Pattern lp = linePattern;
if (lp == null)
linePattern = lp = Pattern.compile(LINE_PATTERN);
return lp;
}
为什么要以如此复杂的方式进行操作,而不仅仅是说
private static Pattern linePattern() {
if (linePattern == null)
linePattern = Pattern.compile(LINE_PATTERN);
return linePattern;
}
在这里使用局部变量(lp
)有什么意义?这是某种优化技术吗?还是预防并发修改?但是linePattern
不能再次设置为null
,因为此方法是唯一对其进行修改的地方。
答案 0 :(得分:3)
我相信这完全是与volatile
和linePattern
字段一起使用的separatorPattern
关键字
private static volatile Pattern separatorPattern;
private static volatile Pattern linePattern;
Java编程语言允许线程访问共享变量(第17.1节)。通常,为确保共享变量被一致且可靠地更新,线程应通过获取通常对这些共享变量强制互斥的锁来确保其专有使用此类变量。
Java编程语言提供了第二种机制,即volatile字段,它比出于某些目的的锁定更方便。
字段可以声明为volatile,在这种情况下,Java内存模型可确保所有线程看到的变量值都是一致的
here也可以阅读
声明一个易失的Java变量意味着:
此变量的值永远不会在线程本地缓存:所有读写操作都将直接进入“主内存”;
对变量的访问就像是将其封装在一个已同步的块中,且已同步。
这就是为什么他们首先尝试直接读取字段的值,然后用新值覆盖它的原因
答案 1 :(得分:2)
我认为他们希望避免两次从volatile
字段中读取。
null
return
在他们的版本中,只有
对于“快乐路径”的优化比仅发生一次的“初始设置路径”发生的频率高得多,如果该方法在完成初始化之前被并发调用,则优化最多可以进行几次。 / p>
或者是防止同时进行修改的预防措施?
没有这样的预防措施。如果您在完成设置静态volatile字段之前并发调用linePattern
,该模式将被创建多次(但是没关系),将返回不同的实例,并且将随机选择其中的一个实例(也可以,因为它们是等效的。
任何防止这种情况的措施只会增加我们“幸福之路”的成本,因此只能在由于某种原因该实例确实确实是单身的情况下才可以这样做。