【java基础】volatile使用总结

volatile使用总结

背景

volatile的出现与java的内存模型(JMM)密不可分。
大家都知道,cpu与内存的频率差别巨大,为了提高cpu的使用率,现代计算机都设置有多级缓存(现在最高好像是3级?)。java是跨平台语言,所以jvm规范专门抽象了一层概念模型,用于屏蔽各平台差异,这层概念模型即为JMM。
JMM把内存分成2大块,工作内存和主内存。java线程只与工作内存交互,同时,JMM规定了一套交互协议用于实现工作内存和主内存的数据同步。
java内存模型和jvm内存模型不同,个人理解是,JMM解决的是数据存取问题,jvm内存模型规定了jvm如何使用内存问题。JMM的工作内存应该是用jvm的虚拟机栈实现的?

volatile语义

下面,说一下volatile能实现什么功能。

  1. 保证变量在多线程之间的可见性。
  2. 禁止指令重排序。

语义解释

保证变量在多线程之间的可见性

下边的代码体现了使用volatile关键字前后的区别。

/* 
 * @author https://blog.csdn.net/wjj0535
 * @since JDK 1.8
 */
public class VolatileTest {
    private static volatile int testInt = 0;
//    private static  int testInt = 0;
    public static void main(String[] args) {
        new Thread(){
            @Override
            public void run() {
                while(testInt == 0) {}
                System.out.println("A Thread: return" + System.currentTimeMillis());
            }
        }.start();
        new Thread(){
            @Override
            public void run() {
                while(testInt == 0) {}
                System.out.println("B Thread: return" + System.currentTimeMillis());
            }
        }.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        testInt++;
    }
}

不使用volatile时,A、B线程均处于死循环状态;
使用volatile后,A、B线程会1s后同时退出,控制台打印:

B Thread: return1617774163455
A Thread: return1617774163455

可以看到,没有volatile时,线程使用的工作内存值,所以testInt==0一直成立。使用volatile后,testInt++导致while条件失效,并且两个线程在毫秒级别同时退出。

禁止指令重排序

现代cpu为了提高并行能力,一般会在不影响程序语义的情况下对程序指令重新编排,放进不同的槽位内。这会造成某些语句,如变量赋值等并没有按照程序员期望的顺序执行。用伪代码举个栗子:

boolean isDone = false;
new Thread(){
	public void run(){
		readConfigFileFromDisk();
		isDone = true;
	}
}.start();
new Thread(){
	public void run(){
		while(!isDone){};
		doSomeThing();
	}
}.start();

上述代码,有可能readConfigFileFromDisk()还没执行,doSomeThing()就已经执行了,导致逻辑错误。

注意点

volatile只会保证多线程间的变量的可见性,不会保证变量操作的原子性。
比如语句i++,分三步执行:

  1. 取最新数据
  2. 工作内存执行+1操作
  3. 写回工作内存并通知其他工作内存失效。

执行第二步时,其他线程会同时在执行。所以在高并发场景的原子操作,volatile不适用,还是需要锁来实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值