Volatile 关键字

文章讨论了volatile关键字如何确保内存可见性,以及它与原子性(如synchronized)的区别。通过示例展示了volatile在多线程环境中的行为,尤其是在修改共享变量时可能产生的问题和解决方法。
摘要由CSDN通过智能技术生成

目录

1.volatile 能保证内存可见性

代码示例

2.volatile不保证原子性


1.volatile 能保证内存可见性

volatile修饰的变量,能保证“内存可见性”。

代码在写入volatile修饰的变量的时候,

  • 改变线程工作内存中volatile变量的值
  • 将改变的副本的值从工作内存刷新到主内存

代码在读取volatile修饰的变量的时候,

  • 从主内存中读取volatile变量的最新值到线程的工作内存中
  • 从工作内存中读取volatile变量的副本 
代码示例

在这个代码中

  • 创建两个线程t1和t2
  • t1中包含一个循环,这个循环以flag==0为循环条件
  • t2中从键盘读入一个整数,并把这个整数赋值给flag
  • 预期当用户输入非0的值的时候,t1线程结束
static class Counter {
 public int flag = 0;
}
public static void main(String[] args) {
 Counter counter = new Counter();
 Thread t1 = new Thread(() -> {
 while (counter.flag == 0) {
 // do nothing
 }
 System.out.println("循环结束!");
 });
 Thread t2 = new Thread(() -> {
 Scanner scanner = new Scanner(System.in);
 System.out.println("输⼊⼀个整数:");
 counter.flag = scanner.nextInt();
 });
 t1.start();
 t2.start();
}
// 执⾏效果
// 当⽤⼾输⼊⾮0值时,t1线程循环下不会结束,(这显然是一个bug)

t1读的是自己工作内存中的内容

当t2对flag变量进行修改,此时t1感知不到flag的变化

 如果给flag加上volatile

static class Counter {
 public volatile int flag = 0;
}
// 执⾏效果
// 当⽤⼾输⼊⾮0值时, t1 线程循环能够⽴即结束. 

2.volatile不保证原子性

volatile和synchronized有着本质的区别。synchronized 能够保证原子性,volatile 保证的是内存可见性。

代码示例

这个是最初的演示线程安全的代码

  • 给increase 方法去掉synchronized
  • 给 count 加上 volatile 关键字。
static class Counter {
 volatile public int count = 0;
 void increase() {
 count++;
 }
}
public static void main(String[] args) throws InterruptedException {
 final Counter counter = new Counter();
 Thread t1 = new Thread(() -> {
 for (int i = 0; i < 50000; i++) {
 counter.increase();
 }
 });
 Thread t2 = new Thread(() -> {
 for (int i = 0; i < 50000; i++) {
 counter.increase();
 }
 });
 t1.start();
 t2.start();
 t1.join();
 t2.join();
 System.out.println(counter.count);
}

此时可以看到,最终count的值仍然无法保证是100000.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值