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

本文探讨了Java中volatile关键字的使用场景。volatile保证了多线程环境下变量的可见性,但不保证原子性。文章通过示例说明了当需要确保单一操作的线程安全时,应该使用volatile,而当涉及复合操作时,应使用synchronized。同时指出,不恰当的volatile使用可能导致不可预见的行为,而过度使用则可能影响性能。
摘要由CSDN通过智能技术生成

I have read "When to use 'volatile' in Java?" but I'm still confused. How do I know when I should mark a variable volatile? What if I get it wrong, either omitting a volatile on something that needs it or putting volatile on something that doesn't? What are the rules of thumb when figuring out what variables should be volatile in multithreaded code?

解决方案

You basically use it when you want to let a member variable be accessed by multiple threads but do not need compound atomicity (not sure if this is the right terminology).

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++;

}

}

the above is a bad example, because you need compound atomicity.

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++;

}

}

Now to a valid example:

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);

}

}

}

Now, why can't you just use private static int temperature? In fact you can (in the sense that that your program won't blow up or something), but the change to temperature by the other thread may or may not be "visible" to the main thread.

Basically this means that it is even possible that your app. keeps writing Today's temperature is 0 forever if you don't use volatile (in practice, the value tends to become eventually visible. However, you should not risk not using volatile when necessary, since it can lead to nasty bugs (caused by in-completely constructed objects etc.).

If you put volatile keyword on something that doesn't need volatile, it won't affect your code's correctness (i.e. the behaviour will not change). In terms of performance, it will depend on the JVM implementation. In theory you might get a tiny performance degradation because the compiler can't do reordering optimisations, have to invalidate CPU cache etc., but then again the compiler could prove that your field cannot ever be accessed by multiple threads and remove the effect of volatile keyword completely and compile it to identical instructions.

EDIT:

Response to this comment:

Ok, but why can't we make todaysTemperature synchronized and create a synchronized getter for temperature?

You can and it will behave correctly. Anything that you can with volatile can be done with synchronized, but not vice versa. There are two reasons you might prefer volatile if you can:

Less bug prone: This depends on the context, but in many cases using volatile is less prone to concurrency bugs, like blocking while holding the lock, deadlocks etc.

More performant: In most JVM implementations, volatile can have significantly higher throughput and better latency. However in most applications the difference is too small to matter.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值