我阅读了JDK关于ConcurrentHashMap的源代码.
但以下代码让我感到困惑:
public boolean isEmpty() {
final Segment<K,V>[] segments = this.segments;
...
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:
声明"this.segments":
final Segment<K,V>[] segments;
Run Code Online (Sandbox Code Playgroud)
所以,在这里,在方法的开头,声明了一个相同的类型引用,指向相同的内存.
为什么作者这样写?他们为什么不直接使用this.segments?有什么理由吗?
Mar*_*nik 94
这是涉及volatile变量的无锁代码的典型惯用语.在第一行,您阅读volatile一次,然后使用它.在此期间,另一个线程可以更新volatile,但您只对最初阅读的值感兴趣.
此外,即使有问题的成员变量不是易失性但最终,这个习惯用法与CPU缓存有关,因为从堆栈位置读取比从随机堆位置读取更加缓存友好.本地var最终绑定到CPU寄存器的可能性也更高.
对于后一种情况,实际上存在一些争议,因为JIT编译器通常会处理这些问题,但Doug Lea是在一般原则上坚持使用它的人之一.
lar*_*.li 19
我想这是出于性能考虑,所以我们只需要检索一次字段值.
你可以参考Joshua Bloch的有效java中的单身成语
他的单身人士在这里:
private volatile FieldType field;
FieldType getField() {
FieldType result = field;
if (result == null) {
synchronized(this) {
result = field;
if (result == null)
field = result = computeFieldValue();
}
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
他写道:
此代码可能看起来有点复杂.特别是,对局部变量结果的需求可能不清楚.这个变量的作用是确保该字段在已经初始化的常见情况下只读一次.虽然不是绝对必要的,这样可以提高性能,是适用于低层次的并行编程标准更优雅.在我的机器上,上面的方法比没有局部变量的明显版本快25%.
| 归档时间: |
|
| 查看次数: |
2366 次 |
| 最近记录: |