volatile作用:
1.在多线程中使用,修改被修饰的变量的操作对其他线程可见。即一个线程对变量进行修改,其他线程可以获取最新的修改后的值
2.禁止指令重排序
int num=1; //语句1
String name="小明"; //语句2
boolean flag=true; //语句3
num=6; //语句4
name="张三"; //语句5
代码这么书写顺序,jvm编译后的代码顺序不保证是一样的。jvm在保证不改变结果的同时,对代码进行排序优化。语句1,2,3调换位置并没有对结果造成影响,同样语句4,5调换位置也不影响。
若使用volatile修饰flag,则必须在语句1,2执行完成后,语句3才执行
3.volatile并不能保证操作的原子性,使用volatile需要满足以下条件
a.对变量的写操作不依赖于当前值
b.该变量没有包含在具有其他变量的不变式中
class Demo implements Runnable{
volatile int num=0;
@Override
public void run() {
for (int i=0;i<100;i++){
num++;
}
System.out.println(num);
}
}
//单线程输出是100,多线程情况下输出可能小于100,原因是volatile修饰基础类型数据时候,当操作不是原子性时,volatile对其他线程可见性失效。 num++非原子性操作。
//改成如下操作,synchronized修饰后,保证同时只有一个线程进行修改,输出100
class Demo implements Runnable{
volatile int num=0;
public synchronized void add(){
num++;
}
@Override
public void run() {
for (int i=0;i<100;i++){
add();
}
System.out.println(num);
}
}
本文深入解析了Java中的volatile关键字,探讨其在多线程环境下的作用,包括确保可见性、禁止指令重排序,以及其不能保证操作原子性的限制。通过具体示例说明了如何正确使用volatile,并对比了synchronized关键字在保证原子性上的优势。
1329

被折叠的 条评论
为什么被折叠?



