为什么在执行双重检查锁定时将volatile字段复制到局部变量 [英] Why is the volatile field copied to a local variable when doing double check locking

查看:179
本文介绍了为什么在执行双重检查锁定时将volatile字段复制到局部变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从Effective Java阅读有关双重检查锁定的信息.该代码执行以下操作:

I am reading about double check locking from Effective Java. The code does the following:

private volatile FieldType field;  
FieldType getField() {  
    FieldType result = field;  
    if (result == null) { // First check (no locking)  
        synchronized(this) {   
        result = field;  
        if (result == null) // Second check (with locking)  
            field = result = computeFieldValue();  
        }  
    }  
    return result;  
}    

它说似乎不需要使用result,但实际上可以确保field在已经初始化的常见情况下仅被读取一次.

It says that using result seems unneeded but actually ensures that the field is only read only once in the common case where it is already initialized.

但是我不明白这一点.直接执行if(field == null)有什么区别?我不明白为什么if (result == null)与众不同,更不用说更好了.

But I don't understand this. What is the difference with doing if(field == null) directly? I don't understand why if (result == null) is different, let alone better as stated.

推荐答案

该示例中的想法是,我想结果/字段将被多次使用.访问result更便宜(它不是易失的).

The thinking in that example is that result/field will be used more than once further down I guess. Accessing result is cheaper (it's not volatile).

否则返回时,您将再次读取volatile.

You have a second volatile read when doing the return otherwise.

如果需要,可以使用按需初始化初始化. http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom

Use the initializaton on demand holder pattern instead if you need to do this. http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom

在答案中添加我的一些澄清,以便清楚...

Adding some of my clarifications in the comments to the answer itself for well... clarity:

简短版本:局部变量可以仅位于cpu(之一)中的寄存器中(如果有多个,则位于cpu的核心之一中).那样快就可以了.必须检查一个volatile变量是否存在其他内核/缓存/cpus/内存中的更改,但是详细信息可能是特定于硬件的(缓存行,内存屏障等).但是还有特定于jvm的(例如,热点服务器编译器可能会提升非易失性变量),并且它对重新排序指令施加了限制,以实现可能的性能提升

Short version: A local variable can just be in a register in (one of) the cpu(s) (and in one of the cpu's cores if multiple etc). That's as fast as it gets. A volatile variable must be checked for changes in other cores/caches/cpus/memory, but the details can be very hardware specific (cache lines, memory barriers etc). But also jvm specific, (the hotspot server compiler might hoist non volatile variables for example) and it imposes limits on reordering instructions for possible performance gains as well

这篇关于为什么在执行双重检查锁定时将volatile字段复制到局部变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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