java volatile什么时候用_什么时候在Java中使用volatile关键字?

当你想让一个成员变量被多个线程访问但不需要复合原子性(不确定这是否是正确的术语)时,你基本上使用它。class BadExample {

private volatile int counter;

public void hit(){

/* This operation is in fact two operations:

* 1) int tmp = this.counter;

* 2) this.counter = tmp + 1;

* and is thus broken (counter becomes fewer

* than the accurate amount).

*/

counter++;

}}

以上是一个不好的例子,因为你需要复合原子性。class BadExampleFixed {

private int counter;

public synchronized void hit(){

/*

* Only one thread performs action (1), (2) at a time

* "atomically", in the sense that other threads can not

* observe the intermediate state between (1) and (2).

* Therefore, the counter will be accurate.

*/

counter++;

}}

现在来看一个有效的例子:class GoodExample {

private static volatile int temperature;

//Called by some other thread than main

public static void todaysTemperature(int temp){

// This operation is a single operation, so you

// do not need compound atomicity

temperature = temp;

}

public static void main(String[] args) throws Exception{

while(true){

Thread.sleep(2000);

System.out.println("Today's temperature is "+temperature);

}

}}

现在,为什么你不能使用private static int temperature?实际上你可以(在某种意义上说你的程序不会爆炸或者其他东西),但是temperature另一个线程的改变可能对主线程“可见”,也可能不是“可见”。

基本上这意味着你的应用甚至可能。Today's temperature is 0如果你不使用volatile,它会永远写作(在实践中,这个值最终会变得可见。但是,你不应该冒险在必要时不使用volatile,因为它可能会导致令人讨厌的错误(由完全构造的对象等引起)。 )。

如果将volatile关键字放在不需要的东西上volatile,它不会影响代码的正确性(即行为不会改变)。在性能方面,它将取决于JVM实现。从理论上讲,由于编译器无法进行重新排序优化,不得不使CPU缓存等无效,因此可能会出现微小的性能下降,但再次编译器可以证明多个线程无法访问您的字段并删除volatile关键字的影响完全并将其编译为相同的指令。

编辑:

回复此评论:好的,但是为什么我们不能让todaysTemperature同步并为温度创建一个同步的getter?

你可以,它会表现正常。您可以使用的任何东西volatile都可以完成synchronized,但反之亦然。volatile如果可以,您可能会有两个理由:减少错误:这取决于上下文,但在许多情况下使用volatile不太容易出现并发错误,例如在持有锁时阻塞,死锁等。

性能volatile更高:在大多数JVM实现中,可以具有更高的吞吐量和更好的延迟。然而,在大多数应用中,差异太小而无关紧要。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值