首页 > 其他分享 >volatile

volatile

时间:2024-08-30 13:36:14浏览次数:9  
标签:缓存 变量 屏障 线程 volatile public

可见性问题复现

线程1不会停止,因为线程2改变了a的值,线程1不知道

public class Test {
    public static Integer a = 1;

    public static void main(String[] args) {

        // 线程1 根本停不下来
        new Thread(() -> {
            while (a == 1){
               
            }
        }).start();

		// 线程2 2秒后修改 a 的值
        new Thread(() -> {
            LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2));
            a = 2;
        }).start();
    }
}

但是如果这样写线程1就会停下来,没搞明白...(至少上面的代码证明了可见性的问题)

public class Test {
    public static Integer a = 1;

    public static void main(String[] args) {

        new Thread(() -> {
            while (a == 1){
                LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(500));
                System.out.println("此时变量还是1");
            }
        }).start();


        new Thread(() -> {
            LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2));
            a = 2;
        }).start();
    }
}

第一段代码中,如果变量使用 volatile 修饰,线程1 就会停下来

volatile

可以保证变量的可见性、有序性

可见性

可以理解为,每个线程不是读取自己的工作内存,而是直接读取主内存,每次修改都会回写主内存,更深入的原因是缓存一致性,官方描述如下(不是很理解,后面再看):

当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存行置为无效状态,因此当其他CPU需要读取这个变量时,发现自己缓存中缓存该变量的缓存行是无效的,那么它就会从内存重新读取

有序性

java 代码最终翻译成可执行的机器指令会被优化、或者只能保证赋值操作啥的是准确的,但是不一定就是我们写的代码的顺序,这就是 指令重排序,底层使用内存屏障来完成的,对于 volatile 完整的情况应该是这样的(不是很理解,后面再看)

  1. 在每一个volatile的写(store)之前,加入一个StoreStore屏障和一个LoadStore屏障
  2. 在每一个volatile的写(store)之后,加入一个StoreLoad屏障和一个StroeStore屏障
  3. 在每一个volatile的读(load)之后,加一个LoadLoad屏障和LoadStrore屏障

标签:缓存,变量,屏障,线程,volatile,public
From: https://www.cnblogs.com/cyrushuang/p/18388597

相关文章

  • Volatile的底层原理
    Volatile的底层原理volatile的特点被volatile修饰的变量具有如下特点:1.保证此变量对所有的线程的可见性,不能保证它具有原子性(可见性,是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的)2.禁止指令重排序优化3.volatile的读性能消耗与普通变量几乎相同,但是写......
  • Volatile关键字
    背景volatile关键字是并发编程中的一个比较重要的关键字。它能保证变量/对象在内存中的可见性,同时禁止指令重排序,避免了CPU或者编译器优化带来的可见性问题。在并发编程中,volatile可以去修饰一个变量,或者是一个对象(比如单例模式中就使用了volatile去修饰单例对象)举例说明vola......
  • C++面试基础系列-volatile
    系列文章目录文章目录系列文章目录C++面试基础系列-volatile1.volatile核心规则2.C与C++中volatile区别2.1.C语言中的volatile2.2.C++中的volatile2.3.原子性和顺序2.4.易失性2.5.优化2.6.使用场景2.7.C++特有的特性2.8.C++20引入的变化(如果有)3.volatile常见面试问题4......
  • 关于volatile关键字为什么不能保证原子性(图文分析)
    文章目录概要多线程访问下数据的问题小结概要在网上的很多文章当中,都说到了volatile不可以保证原子性,对于这个关键字的定义解释的很清楚。volatile是Java中的一个关键字,用于修饰变量,它的主要作用是保证变量的可见性和禁止指令重排序。但是对于为什么这个关键字......
  • 面试题:在Java中,volatile 关键字的作用是什么?它与 synchronized 关键字在实现线程同步
    面试题:在Java中,volatile 关键字的作用是什么?它与 synchronized 关键字在实现线程同步方面有何不同?请深入探讨其背后的原理和应用场景。更多答案在这里,手机或电脑浏览器就可以打开, 面霸宝典【全 拼音】.com 这里可以优化简历,模拟面试,企业项目源码,最新最全大厂高并......
  • Java volatile关键字剖析
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录1.volatile关键字介绍2.volatile变量可见性问题3.volatile变量可见性保证3.1Fullvolatile完全易失性可见性保证3.2指令重新排序挑战3.3volatile的Happens-Before保证4.volatile并不......
  • volatile
    共享变量+volitale保证线程间的可见性禁止指令重排/*一、booleanflag运行结果:线程1flag=false【一直阻塞】二、volatilebooleanflag运行结果:线程2循环次数=71585922线程2over线程1flag=false**/publicclassT{privatestaticvolatilebooleanfla......
  • 面试官:说说volatile应用和实现原理?
    volatile是并发编程中的重要关键字,它的名气甚至是可以与synchronized、ReentrantLock等齐名,也是属于并发编程五杰之一。需要注意的是volatile并不能保证原子性,因此使用volatile并没有办法保证线程安全。并发编程五杰:PS:“并发编程五杰”是我个人起的名字,大家也不用太......
  • 【多线程-从零开始-伍】volatile关键字和内存可见性问题
    volatile关键字importjava.util.Scanner;publicclassDemo2{privatestaticintn=0;publicstaticvoidmain(String[]args){Threadt1=newThread(()->{while(n==0){//啥都不写......
  • c语言学习 volatile __attribute__ const
    1volatile在C语言中,volatile是一个类型修饰符,用于告诉编译器某个变量的值可能会被外部因素改变,从而避免编译器对该变量进行优化。这在多线程编程或硬件编程中非常重要。用法volatileintmyVar;何时使用volatile硬件寄存器:当变量映射到某个硬件寄存器。中断服务例......