为什么JDK源代码采用`volatile`实例的`final`副本 [英] Why does JDK sourcecode take a `final` copy of `volatile` instances

查看:59
本文介绍了为什么JDK源代码采用`volatile`实例的`final`副本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我读了JDK关于ConcurrentHashMap的源代码。

I read the JDK's source code about ConcurrentHashMap.

但是下面的代码让我很困惑:

But the following code confused me:

public boolean isEmpty() {
    final Segment<K,V>[] segments = this.segments;
    ...
}

我的问题是:

宣布this.segments:

"this.segments" is declared:

final Segment<K,V>[] segments;

所以,在这里,在方法的开头,声明了一个相同的类型引用,指向相同的记忆。

So, here, in the beginning of the method, declared a same type reference, point to the same memory.

为什么作者这样写?他们为什么不直接使用this.segments?是否有某些原因?

Why did the author write it like this? Why didn't they use this.segments directly? Is there some reason?

推荐答案

这是一个典型的无锁代码,涉及 volatile 变量。在第一行,您只需阅读 volatile ,然后使用它。在此期间,另一个线程可以更新 volatile ,但您只对最初阅读的值感兴趣。

This is an idiom typical for lock-free code involving volatile variables. At the first line you read the volatile once and then work with it. In the meantime another thread can update the volatile, but you are only interested in the value you initially read.

此外,即使有问题的成员变量不是易失性但最终,这个习惯用法与CPU缓存有关,因为从堆栈位置读取比从随机堆位置读取更加缓存友好。本地var最终可能最终绑定到CPU寄存器。

Also, even when the member variable in question is not volatile but final, this idiom has to do with CPU caches as reading from a stack location is more cache-friendly than reading from a random heap location. There is also a higher chance that the local var will end up bound to a CPU register.

对于后一种情况,实际上存在一些争议,因为JIT编译器通常会照顾这些顾虑,但Doug Lea是一般原则上坚持这一点的人之一。

For this latter case there is actually some controversy, since the JIT compiler will usually take care of those concerns, but Doug Lea is one of the guys who sticks with it on general principle.

这篇关于为什么JDK源代码采用`volatile`实例的`final`副本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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