getter方法是Java中volatile的替代方法吗? [英] Is getter method an alternative to volatile in Java?

查看:75
本文介绍了getter方法是Java中volatile的替代方法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道私有布尔字段的getter方法是否强制其他线程获取最新的更新值?这是挥发性领域的替代方法吗? 例如:

I'm wondering if a getter method for a private boolean field forces the other threads to get the latest updated value? Is this an alternative for volatile field? For example:

Class A {
    private boolean flag;

    public boolean getFlag() {
        return this.flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}

vs

Class B {
    public volatile boolean flag;
}

是真的,整个对象是由线程(包括私有字段)缓存的,所以当我调用getter时,它将返回缓存的私有字段吗?

Is it true that the entire object is cached by a thread (including the private field), so that when I call the getter it will return the cached private field?

推荐答案

不,getter不会导致字段同步.

No, getter will not cause the field to be synchronized.

在谈论在多线程环境中读写基元时,我们遇到了三个问题,这是由CPU引起的

when talking about reading and writing a primitive in a multi-threaded environment, we have three problems, caused by the CPU

  1. 原子性:它可能需要存储或装载操作多个汇编指令,例如,在32位CPU上将其写入64位整数.当前线程可以在指令序列的中间由操作系统置于休眠状态.
  2. 可见性:在一个内核上运行的线程可能无法读取其他内核的其他线程已写入的最新值.仅仅是因为CPU这么说.
  3. 重新排序:为了使程序运行更快,CPU视需要混合汇编指令的顺序.

Getter不能解决所有这些问题.即使是这样,JIT编译器也可能会完全优化该功能.比什么?

Getter doesn't solve any of these problem. even if it was, the JIT compiler may completely optimize that function away. than what?

易失性是解决上述问题的方法之一.锁也一样.它们确保一个线程读取基元的最新值,或确保正在写入的值对其他线程可见.它们还会使汇编指令完全按其编译的方式运行,而不会进行任何混合.

Volatile is one of the ways to solve of the problems above. so does a lock. they ensure that one thread reads the latest value of the primitive, or make sure that a value being written is visible to other threads. they also cause the assembly instructions to run exactly as they were compiled, without any blending.

请注意,生成的程序集看上去可能与您在代码中编写的程序集完全不同.您问自己:我写的代码是从flag读取的,为什么程序不从字段本身读取?"编译器可能会执行其认为合适的一切,以尽可能快地完成汇编.通过 not 不添加任何锁或易失性说明符,您基本上告诉编译器不涉及多线程访问,并且编译器(以及随后的CPU)可以自由地假定该对象未被任何对象触及.多线程.可能不是一开始就创建了该对象. JIT编译器可能会说:好吧,在寄存器中声明此布尔值,然后将其视为整个对象".很有可能.

As a side note, the generated assembly may look completely different from what you have written in your code. you ask yourself "I wrote in my code to read from flag, so why wouldn't the program read from the field itself?" the compiler may do whatever it sees fit to make the assembly fast as possible. by not adding any locks or volatile specifier, you basically told the compiler that no multi-threaded access is involved and the compiler (and subsequently, the CPU) is free to assume that the object is not touched by multiple threads. it could be that this object may not be created at the first place. the JIT compiler may say "well, declare this boolean in a register and treat that as the entire object". it is very possible.

整个对象是否由线程缓存(包括私有字段)是真的,所以当我调用getter时,它将返回缓存的私有字段吗?

Is it true that the entire object is cached by a thread (including the private field), so that when I call the getter it will return the cached private field?

您不能假定那样.它取决于JVM,底层操作系统和底层CPU.它可能会全部,部分或根本不被完全缓存.提醒您,即使对象被缓存,它的大部分CPU也有不只一个缓存行,它在哪里缓存?在寄存器中还是其中一条缓存行中?

You cannot assume that. it is up to the JVM, the underlying OS and the underlying CPU. it may be cached completely, partially or not at all. to remind you, most of the CPU's out there have more than one cache line, even if the object is cached, where is it cached? in the registers or one of the cache lines?

这篇关于getter方法是Java中volatile的替代方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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