当前位置: 首页> 教育> 高考 > volatile

volatile

时间:2025/8/22 20:29:13来源:https://blog.csdn.net/weixin_74144099/article/details/141942393 浏览次数:0次

文章目录

  • volatile
    • 可见性
    • 指令重排
    • volatile原理

volatile

可见性

问题:t 线程会从自己的高速缓存中读取run值,而无法获取到更新后的值,导致程序无法结束。

@Slf4j
public class Test05 {static boolean run = true;public static void main(String[] args) {new Thread(() ->{int i=0;while(run){i++;}}).start();log.info("开始任务");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}run = false;log.info("停止任务");}
}

解决方法:给run加上volatile(易变的)属性,避免从工作缓存中读取值,而必须到主缓存中获取值,保证数据在不同线程中的可见性。

static volatile boolean run = true;

指令重排

问题:r1的结果可能为0,因为actor2中的两行代码可能会发生指令重排,导致执行顺序颠倒。

int num = 0;
boolean ready = false; 
// 线程1 执行此方法 
public void actor1(I_Result r) {if(ready) { r.r1 = num + num;}else {r.r1 = 1;} 
}
// 线程2 执行此方法 
public void actor2(I_Result r) {num = 2;ready = true;
}

解决:给ready添加volatile关键字

volatile boolean ready = false;

volatile原理

volatile的底层实现原理是内存屏障,Memory Barrier(Memory Fence)

  • 对 volatile 变量的写指令后会加入写屏障
  • 对 volatile 变量的读指令前会加入读屏障

而有了屏障之后,可见性和有序性就有了很好的解决。

可见性:

  • 写屏障(sfence)保证在该屏障之前的,对共享变量的改动,都同步到主存当中
  • 读屏障(lfence)保证在该屏障之后,对共享变量的读取,加载的是主存中新数据

有序性:

  • 写屏障会确保指令重排序时,不会将写屏障之前的代码排在写屏障之后
  • 读屏障会确保指令重排序时,不会将读屏障之后的代码排在读屏障之前

虽然volatile可以保证可见性和有序性,但它并不能保证复合操作(如自增、自减或检查后执行逻辑)的原子性。因此,volatile并不能替代同步机制(如synchronized)来控制对共享资源的并发访问。

关键字:volatile

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: