我想知道私有布尔字段的getter方法是否强制其他线程获取最新的更新值?这是不稳定场的替代品吗? 例如:
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时它会返回缓存的私有字段吗?
答案 0 :(得分:3)
不,getter不会导致字段同步。
在谈论在多线程环境中读取和编写基元时,我们有三个问题,由CPU引起
Getter没有解决任何这些问题。即使它是,JIT编译器也可以完全优化该功能。比什么?
挥发性是解决上述问题的方法之一。锁定也是如此。它们确保一个线程读取基元的最新值,或确保正在写入的值对其他线程可见。它们还使组装指令完全按照编译方式运行,而不进行任何混合。
作为旁注,生成的程序集可能与您在代码中编写的内容完全不同。你问自己“我在我的代码中写了flag
来读,所以为什么程序不会从字段本身读取?”编译器可以做任何它认为合适的事情,以使组件尽可能快。通过不添加任何锁或易失性说明符,您基本上告诉编译器不涉及多线程访问,并且编译器(以及随后的CPU)可以自由地假设对象未被触及多线程。可能是这个对象可能不会在第一时间创建。 JIT编译器可能会说“好吧,在寄存器中声明这个布尔值并将其视为整个对象”。很有可能。
编辑:整个对象是否被线程(包括私有字段)缓存是真的,所以当我调用getter时它会返回缓存的私有字段吗?
你无法想象。它取决于JVM,底层操作系统和底层CPU。它可以完全缓存,部分缓存或根本不缓存。提醒你,大多数CPU都有多个缓存行,即使对象被缓存,缓存在哪里?在寄存器或其中一个缓存行?
答案 1 :(得分:1)
我想知道私有布尔字段的getter方法是否强制其他线程获取最新的更新值
没有。在没有volatile
关键字的情况下,它不会强制其他线程获取最新值。
这是不稳定领域的替代方案吗?
没有。在没有boolean
关键字的情况下,简单的getter调用不能替代获得volatile
值的最新值。
解决问题的更好解决方案:使用AtomicBoolean
可以原子方式更新的布尔值。有关原子变量属性的描述,请参阅java.util.concurrent.atomic包规范。
几个有用的链接:
What is the difference between atomic / volatile / synchronized?
答案 2 :(得分:0)
getter强制线程获取未缓存的值?这是不稳定场的替代方案吗?
不,getter方法不会强制执行任何操作,因此您必须需要volatile
,以便当前线程看到其他线程更新的最新值,否则,您可能会看到过时的值。 / p>
您需要了解here中的以下文字,并明确了解原子访问的概念。
volatile变量始终对其他线程可见。它 也意味着当一个线程读取一个volatile变量时,它看不到 只是对易变的最新变化
答案 3 :(得分:0)
如果您在这两种方法中使用了 synchronized 关键字,则是:
public synchronized boolean getFlag() {
return this.flag;
}
public synchronized void setFlag(boolean flag) {
this.flag = flag;
}
那么这两个方法就相当于在实例变量上使用了volatile