精华内容
下载资源
问答
  • volatile关键字虽然从字面上理解起来比较简单,但是要用好不是一件容易的事情。这篇文章主要介绍了Java中volatile关键字作用与用法详解的相关资料,需要的朋友可以参考下
  • 在本文里我们给大家分享的是关于java volatile关键字作用及使用场景的相关知识点内容,需要的朋友们学习下。
  • 一个定义为volatile 的变量是说这变量可能会被意想不到地改变,这样,编 译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必 须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里...
  • volatile关键字作用

    2020-02-21 20:24:51
    内存可见性:保证变量的可见性:当一个被volatile关键字修饰的变量被一个线程修改的时候,其他线程可以立刻得到修改之后的结果。当一个线程向被volatile关键字修饰的变量写入数据的时候,虚拟机会强制它被值刷新到主...

    一、作用简述

    1. 内存可见性:保证变量的可见性:当一个被volatile关键字修饰的变量被一个线程修改的时候,其他线程可以立刻得到修改之后的结果。当一个线程向被volatile关键字修饰的变量写入数据的时候,虚拟机会强制它被值刷新到主内存中。当一个线程用到被volatile关键字修饰的值的时候,虚拟机会强制要求它从主内存中读取。
    2. 屏蔽JVM指令重排序(防止JVM编译源码生成class时使用重排序):指令重排序是编译器和处理器为了高效对程序进行优化的手段,它只能保证程序执行的结果是正确的,但是无法保证程序的操作顺序与代码顺序一致。这在单线程中不会构成问题,但是在多线程中就会出现问题。非常经典的例子是在单例方法中同时对字段加入voliate,就是为了防止指令重排序。

    二、深入讲解

    在Java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉。

    Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块(synchronized) 和 volatile 关键字机制。

    1、synchronized(不做过多解释)

    同步块大家都比较熟悉,通过 synchronized 关键字来实现,所有加上synchronized 和 块语句,在多线程访问的时候,同一时刻只能有一个线程能够执行synchronized 修饰的方法 或者 代码块。

    2、volatile

    2.1 内存可见性详解

    用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的值。volatile很容易被误用,用来进行原子性操作。如果要深入了解volatile关键字的作用,就必须先来了解一下JVM在运行时候的内存分配过程:

    在 java 垃圾回收整理一文中,描述了jvm运行时刻内存的分配。其中有一个内存区域是jvm栈,每一个线程运行时都有一个线程栈,线程栈保存了线程运行时候变量值信息。当线程访问某一个对象时候值的时候,首先通过对象的引用找到对应在堆内存的变量的值,然后把堆内存变量的具体值load到线程本地内存中,建立一个变量副本,之后线程就不再和对象在堆内存变量值有任何关系,而是直接修改该线程栈中的副本变量的值,在修改完之后的某一个时刻(线程退出之前),自动把线程变量副本的值回写到对象在堆中变量。这样在堆中的对象的值就产生变化了。下面一幅图描述这写交互:

    那么在了解完JVM在运行时候的内存分配过程以后,我们开始真正深入的讨论volatile的具体作用

    请看代码:

    public class VolatileTest extends Thread {
        
        boolean flag = false;
        int i = 0;
        
        public void run() {
            while (!flag) {
                i++;
            }
        }
        
        public static void main(String[] args) throws Exception {
            VolatileTest vt = new VolatileTest();
            vt.start();
            Thread.sleep(2000);
            vt.flag = true;
            System.out.println("stope" + vt.i);
        }
    }

    上面的代码是通过标记flag来控制VolatileTest线程while循环退出的例子!

    下面让我用伪代码来描述一下我们的程序

    • 首先创建 VolatileTest vt = new VolatileTest();
    • 然后启动线程 vt.start();
    • 暂停主线程2秒(Main) Thread.sleep(2000);
    • 这时的vt线程已经开始执行,进行i++;
    • 主线程暂停2秒结束以后将 vt.flag = true;
    • 打印语句 System.out.println("stope" + vt.i); 在此同时由于vt.flag被设置为true,所以vt线程在进行下一次while判断 while (!flag) 返回假 结束循环 vt线程方法结束退出!
    • 主线程结束

    执行预期:2秒钟以后控制台打印stope-202753974。之后由于变量被设置成true,导致线程退出->进程退出

    实际执行结果:可是奇怪的事情发生了 程序并没有退出。vt线程仍然在运行,也就是说我们在主线程设置的 vt.flag = true;没有起作用。

    在这里我需要说明一下,有的同学可能在测试上面代码的时候程序可以正常退出。那是因为你的JVM没有优化造成的!在DOC下面输入 java -version 查看 如果显示Java HotSpot(TM) ... Server 则JVM会进行优化。

    如果显示Java HotSpot(TM) ... Client 为客户端模式,需要设置成Server模式  设置方法问Google

    问题出现了,为什么我在主线程(main)中设置了vt.flag = true; 而vt线程在进行判断flag的时候拿到的仍然是false?

     那么按照我们上面所讲的 “JVM在运行时候的内存分配过程” 就很好解释上面的问题了。

     首先 vt线程在运行的时候会把 变量 flag 与 i (代码3,4行)从“主内存”  拷贝到 线程栈内存(上图的线程工作内存)

     然后 vt线程开始执行while循环 

    while (!flag) {
       i++;
    }

    while (!flag)进行判断的flag 是在线程工作内存(线程的栈内存)当中获取,而不是从 “主内存”(堆内存)中获取。

    i++; 将线程内存中的i++; 加完以后将结果写回至 "主内存",如此重复。整个过程只完成了将修改后的i值写回主存,而获取时没有重新重主存拿,还是从栈内存拿的(一直读的都是首次从主存load到线程工作内存的值false)

    然后再说说主线程的执行过程。 我只说明关键的地方 

    vt.flag = true;

    主线程将vt.flag的值同样 从主内存中拷贝到自己的线程工作内存 然后修改flag=true. 然后再将新值回到主内存。

    这就解释了为什么在主线程(main)中设置了vt.flag = true; 而vt线程在进行判断flag的时候拿到的仍然是false。那就是因为vt线程每次判断flag标记的时候是从它自己的“工作内存中”取值,而并非再次从主内存中取值!

    这也是JVM为了提供性能而做的优化。那我们如何能让vt线程每次判断flag的时候都强制它去主内存中取值呢。这就是volatile关键字的作用。

    再次修改我们的代码:

    public class VolatileTest extends Thread {
        
        volatile boolean flag = false;
        int i = 0;
        
        public void run() {
            while (!flag) {
                i++;
            }
        }
        
        public static void main(String[] args) throws Exception {
            VolatileTest vt = new VolatileTest();
            vt.start();
            Thread.sleep(2000);
            vt.flag = true;
            System.out.println("stope" + vt.i);
        }
    }

    在flag前面加上volatile关键字,强制所有工作线程每次读取该值的时候都去“主内存”中取值在试试我们的程序吧,已经正常退出了。

    2.2 防止指令重排序(防止JVM编译源码生成class时使用重排序)

    编译期重排序的典型就是通过调整指令顺序,做到在不改变程序语义的前提下,尽可能减少寄存器的读取、存储次数,充分复用寄存器的存储值。
    比如我们有如下代码:

    int x = 10;
    int y = 9;
    x = x+10;

    假设编译器直接对上面代码进行编译,不进行重排序的话,我们简单分析一下执行这段代码的过程,首先加载x变量的内存地址到地址寄存器,然后会加载10到数据寄存器,然后CPU通过mov指令把10写入到地址寄存器中指定的内存地址中。然后加载y变量的内存地址到地址寄存器,加载9到数据寄存器,把9写入到内存地址中。进行第三行执行时,我们发现CPU需要重新加载x的内存地址和数据到寄存器,但如果我把第三行和第二行换一下顺序,那么执行过程中对于寄存器的存取就可以少很多次,同时对于程序结果没有任何影响。

    另一个例子可以看下面的双重检查锁构造单例的代码:

    public class Singleton {
        private volatile static Singleton singleton;
     
        private Singleton() {}
     
        public static Singleton getInstance() {
            if (singleton == null) { // 1
                sychronized(Singleton.class) {
                    if (singleton == null) {
                        singleton = new Singleton(); // 2
                    }
                }
            }
            return singleton;
        }
    } 
    

    实际上当程序执行到2处的时候,如果我们没有使用volatile关键字修饰变量singleton,就可能会造成错误。这是因为使用new关键字初始化一个对象的过程并不是一个原子的操作,它分成下面三个步骤进行:

    1. 给 singleton 分配内存
    2. 调用 Singleton 的构造函数来初始化成员变量
    3. 将 singleton 对象指向分配的内存空间(执行完这步 singleton 就为非 null 了)

    如果虚拟机存在指令重排序优化,则步骤2和3的顺序是无法确定的。如果A线程率先进入同步代码块并先执行了3而没有执行2,此时因为singleton已经非null。这时候线程B到了1处,判断singleton非null并将其返回使用,因为此时Singleton实际上还未初始化,自然就会出错。

    虽然singleton使用synchronized进行了修饰,但是sychronized可以解决内存可见性,但是不能解决重排序问题。

    但是特别注意在jdk 1.5以前的版本使用了volatile的双检锁还是有问题的。其原因是Java 5以前的JMM(Java 内存模型)是存在缺陷的,即使将变量声明成volatile也不能完全避免重排序,主要是volatile变量前后的代码仍然存在重排序问题。这个volatile屏蔽重排序的问题在jdk 1.5 (JSR-133)中才得以修复:这时候jdk对volatile增强了语义,对volatile对象都会加入读写的内存屏障,以此来保证可见性,这时候2-3就变成了代码序而不会被CPU重排,所以在这之后才可以放心使用volatile。

    展开全文
  • Java volatile关键字作用

    千次阅读 2018-11-02 09:59:53
    当一个共享变量被volatile修饰时,它会保证修改的值立即被更新到主存“, 这里的”保证“ 是如何做到的?和 JIT的具体编译后的CPU指令相关吧?  volatile特性  内存可见性:通俗来说就是... 通过关键字sychronize...

    当一个共享变量被volatile修饰时,它会保证修改的值立即被更新到主存“, 这里的”保证“ 是如何做到的?和 JIT的具体编译后的CPU指令相关吧?

      volatile特性

      内存可见性:通俗来说就是,线程A对一个volatile变量的修改,对于其它线程来说是可见的,即线程每次获取volatile变量的值都是最新的。

      volatile的使用场景

      通过关键字sychronize可以防止多个线程进入同一段代码,在某些特定场景中,volatile相当于一个轻量级的sychronize,因为不会引起线程的上下文切换,但是使用volatile必须满足两个条件:

      1、对变量的写操作不依赖当前值,如多线程下执行a++,是无法通过volatile保证结果准确性的;

      2、该变量没有包含在具有其它变量的不变式中,这句话有点拗口,看代码比较直观。

    public class NumberRange {
      private volatile int lower = 0;
    
      private volatile int upper = 10;
    
      public int getLower() { return lower; }
    
      public int getUpper() { return upper; }
    
      public void setLower(int value) {
    
         if (value> upper)
    
         throw new IllegalArgumentException(...);
    
         lower = value;
    
      }
    
      public void setUpper(int value) {
    
         if (value < lower)
    
         throw new IllegalArgumentException(...);
    
         upper = value;
    
       }
    }

    上述代码中,上下界初始化分别为0和10,假设线程A和B在某一时刻同时执行了setLower(8)和setUpper(5),且都通过了不变式的检查,设置了一个无效范围(8, 5),所以在这种场景下,需要通过sychronize保证方法setLower和setUpper在每一时刻只有一个线程能够执行。

    上述如果没有了解volatile的作用,那么看下下面的例子可以看出volatile在实际中的作用

    下面是我们在项目中经常会用到volatile关键字的两个场景:

      1、状态标记量

      在高并发的场景中,通过一个boolean类型的变量isopen,控制代码是否走促销逻辑,该如何实现?

    public class ServerHandler {
    
          private volatile isopen;
    
          public void run() {
             
            if (isopen) {
    
                //促销逻辑
                  
            } else {
    
               //正常逻辑
                  
            }
              
        }
    
        public void setIsopen(boolean isopen) {
    
           this.isopen = isopen
              
        }      
    }

    上述一个简单的案例我们可以清楚的看到,现实场景中用户执行了多线程中run()方法,如果需要开启促销逻辑,那么只需要后台设置调用setIsopen(true) 方法,就能很好的控制多线程中方法控制的问题了,该放说明volatile关键字的作用就是告诉该执行方法时时获取最新变量值。

     如何保证内存可见性?

      在java虚拟机的内存模型中,有主内存和工作内存的概念每个线程对应一个工作内存,并共享主内存的数据,下面看看操作普通变量和volatile变量有什么不同:

      1、对于普通变量:读操作会优先读取工作内存的数据,如果工作内存中不存在,则从主内存中拷贝一份数据到工作内存中;写操作只会修改工作内存的副本数据,这种情况下,其它线程就无法读取变量的最新值。

      2、对于volatile变量,读操作时JMM会把工作内存中对应的值设为无效,要求线程从主内存中读取数据;写操作时JMM会把工作内存中对应的数据刷新到主内存中,这种情况下,其它线程就可以读取变量的最新值。

     

    volatile变量的内存可见性是基于内存屏障(Memory Barrier)实现的,什么是内存屏障?内存屏障,又称内存栅栏,是一个CPU指令。在程序运行时,为了提高执行性能,编译器和处理器会对指令进行重排序,JMM为了保证在不同的编译器和CPU上有相同的结果,通过插入特定类型的内存屏障来禁止特定类型的编译器重排序和处理器重排序,插入一条内存屏障会告诉编译器和CPU:不管什么指令都不能和这条Memory Barrier指令重排序。

     

    class Singleton {
    
          private volatile static Singleton instance;
    
          private int a;
    
          private int b;
    
          private int b;
    
          public static Singleton getInstance() {
              
            if (instance == null) {
    
                  syschronized(Singleton.class) {
                      
                    if (instance == null) {
    
                          a = 1; // 1
                          b = 2; // 2
                          instance = new Singleton(); // 3
                          c = a + b; // 4
                    }
                      
                }
                  
            }
     
            return instance;  
        } 
    }

    1、如果变量instance没有volatile修饰,语句1、2、3可以随意的进行重排序执行,即指令执行过程可能是3214或1324。

    2、如果是volatile修饰的变量instance,会在语句3的前后各插入一个内存屏障。

    展开全文
  • 单例模式是程序设计中经常用到的,简单便捷的设计模式,也是很多程序猿对设计模式入门的第一节课。其中最经典的一种写法是: ...//volatile关键字防止指令重排 private Singleton(){} public static Sing...

      单例模式是程序设计中经常用到的,简单便捷的设计模式,也是很多程序猿对设计模式入门的第一节课。其中最经典的一种写法是:

    class Singleton {
        private volatile static Singleton instance;//volatile关键字防止指令重排
        private Singleton(){}
        public static Singleton getInstance() {
            if ( instance == null ) { //一重判断
                synchronized (Singleton.class) {//对Singleton.class上锁
                    if ( instance == null ) {//二重判断
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    

      其中有两个关键的地方:1,初始化instance实例的时候,采用两重判断对Singleton.class上锁。

                 2,静态变量instance使用了volatile关键字进行修饰。

      第一个问题相对比较好理解  

            if ( instance == null ) { //一重判断
                synchronized (Singleton.class) {//对Singleton.class上锁
                    if ( instance == null ) {//二重判断
                        instance = new Singleton();
                    }
                }
            }

      

      sychronized关键字锁住Singleton类而不是instance对象,是因为,此时instance为空,加sychronized没有意义。
    第一重判断的意义在于:如果instance非空,就跳过了锁的步骤,减少加锁的资源开销。但是由于第一重判断在代码锁之外,如果不同线程同时访问到install==null,会先后阻塞执行代码锁内的内容。所以在代码锁内加第二重判断就很有必要了,避免第一个线程获取实例后,第二个线程获得资源锁又执行了一次instance的初始化,产生两个不同的实例。

      很多人不理解instance实例在声明时加volatile关键字的作用,或者是发现别人这么写了,自己也跟着这么写。对volatile关键字的解释,很多地方只是提了句“当要求使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,它可以防止指令重排”,这里不想对这句话进行展开解释,想详细了解可以参考文章
      https://www.cnblogs.com/shan1393/p/8999683.html
      https://www.cnblogs.com/xrq730/p/7048693.html

      instance = new Singleton()看上去只有一句话,但java的初始化成员变量包括内存分配、初始化、返回对象在堆上的引用等一系列操作。对于synchronized代码块内,一条语句完整执行是没有问题的。但如果发生了指令重排,先返回对象在堆上的引用,再进行初始化。对于另一个执行到一重判断的线程来说,由于instance已经指向了堆上的一段内存空间,那么instance就不为空,会将未完成初始化的对象返回给其他函数调用,引发一系列不安全隐患。加了volatile关键字,可以保证返回对象在对上的引用发生在初始化之后,避免了这种情况的发生。这就是单例模式下 instance加volatile关键字的作用。

    转载于:https://www.cnblogs.com/acesui/p/9557501.html

    展开全文
  • java volatile关键字作用及使用场景 1. volatile关键字的作用:保证了变量的可见性(visibility)。被volatile关键字修饰的变量,如果值发生了变更,其他线程立马可见,避免出现脏读的现象。如以下代码片段,...

    1. volatile关键字的作用:保证了变量的可见性(visibility)。被volatile关键字修饰的变量,如果值发生了变更,其他线程立马可见,避免出现脏读的现象。如以下代码片段,isShutDown被置为true后,doWork方法仍有执行。如用volatile修饰isShutDown变量,可避免此问题。

    复制代码

     1 public class VolatileTest3 {
     2     static class Work {
     3         boolean isShutDown = false;
     4 
     5         void shutdown() {
     6             isShutDown = true;
     7             System.out.println("shutdown!");
     8         }
     9 
    10         void doWork() {
    11             while (!isShutDown) {
    12                 System.out.println("doWork");
    13             }
    14         }
    15     }
    16 
    17     public static void main(String[] args) {
    18         Work work = new Work();
    19 
    20         new Thread(work::doWork).start();
    21         new Thread(work::doWork).start();
    22         new Thread(work::doWork).start();
    23         new Thread(work::shutdown).start();
    24         new Thread(work::doWork).start();
    25         new Thread(work::doWork).start();
    26         new Thread(work::doWork).start();
    27     }
    28 }

    复制代码

    出现脏读时,运行结果如下:

    2. 为什么会出现脏读?

    Java内存模型规定所有的变量都是存在主存当中,每个线程都有自己的工作内存。线程对变量的所有操作都必须在工作内存中进行,而不能直接对主存进行操作。并且每个线程不能访问其他线程的工作内存。变量的值何时从线程的工作内存写回主存,无法确定。

    3. happens-before规则的理解与勘误

    在网上查volatile关键字相关信息时,多篇博客提到了happens-before原则,个人对此原则的理解是:当操作该volatile变量时,所有前序对该变量的操作都已完成(如不存在已变更,但未写回主存的情况),所有后续对该变量的操作,都未开始。仅此而已。

    这里,我认为网上很常见的一个理论对此理解有误,如下图。此观点认为,由于volatile变量flag的happens-before原则,所以A线程2处对其的写操作一定先于B线程3处对其的读操作。其实这种观点是有逻辑缺陷的,如果存在一个C线程,先读取flag的值,后写入flag的值,那C线程的执行时机是什么呢?如果还有其他D、E线程呢。。。对于这段代码的正确理解是,只要3处拿到的flag是true,那么a的值一定是1,而不是0.因为volition修饰的变量,处理器不会对其进行重排序,所以1处对a的赋值,一定发生在2处对flag的赋值之前。如果flag不是volatile变量,那么1处和2处代码的执行顺序是无法保证的(处理器的指令重排序),虽然大部分情况1会先于2执行。happens-before原则约束的并不是多线程对同一变量的读和写操作之间的顺序,而是保证读操作时,前序所有对该变量的写操作已生效(写回主存)。

     

     

    验证如下:

    复制代码

     1 public class VolatileTest {
     2     static class A {
     3         int a = 0;
     4         volatile boolean flag = false;
     5 
     6         void writer() {
     7             a = 1;                   //1
     8             flag = true;               //2
     9             System.out.println("write");
    10         }
    11 
    12         void reader() {
    13             if (flag) {                //3
    14                 int i =  a;           //4
    15                 System.out.println("read true");
    16                 System.out.println("i is :" + i);
    17             } else {
    18                 int i = a;
    19                 System.out.println("read false");
    20                 System.out.println("i is :" + i);
    21             }
    22         }
    23 
    24     }
    25 
    26     public static void main(String[] args) {
    27         A aaa = new A();
    28         new Thread(() -> aaa.reader()).start();
    29         new Thread(() -> aaa.writer()).start();
    30     }
    31 }

    复制代码

    运行结果如下,在写操作执行之前,读操作已完成

     

     4. volatile关键字使用场景

    注意:volatile只能保证变量的可见性,不能保证对volatile变量操作的原子性,见如下代码:

     

    复制代码

     1 public class VolatileTest2 {
     2     static class A {
     3         volatile int a = 0;
     4         void increase() {
     5             a++;
     6         }
     7         int getA(){
     8             return a;
     9         }
    10     }
    11 
    12     public static void main(String[] args) {
    13         A a = new A();
    14 
    15         new Thread(() -> {
    16             for (int i = 0;i < 1000;i++) {
    17                 a.increase();
    18             }
    19             System.out.println(a.getA());
    20         }).start();
    21         new Thread(() -> {
    22             for (int i = 0;i < 2000;i++) {
    23                 a.increase();
    24             }
    25             System.out.println(a.getA());
    26         }).start();
    27         new Thread(() -> {
    28             for (int i = 0;i < 3000;i++) {
    29                 a.increase();
    30             }
    31             System.out.println(a.getA());
    32         }).start();
    33         new Thread(() -> {
    34             for (int i = 0;i < 4000;i++) {
    35                 a.increase();
    36             }
    37             System.out.println(a.getA());
    38         }).start();
    39         new Thread(() -> {
    40             for (int i = 0;i < 5000;i++) {
    41                 a.increase();
    42             }
    43             System.out.println(a.getA());
    44         }).start();
    45     }
    46 }

    复制代码

     

    运行结果如下,volatile无法保证a++操作的原子性。

    展开全文
  • 嵌入式开发-c语言中volatile关键字作用C 语言语言中中volatile 关键字关键字作用作用语言语言中中 关键字关键字作用作用一个定义为volatile 的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个...
  • volatile关键字作用

    万次阅读 多人点赞 2019-06-09 23:46:30
    volatile关键字作用
  • volatile关键字及其作用(举例说明)

    千次阅读 2021-01-31 22:49:33
    volatile关键字及其作用 一、多线程并发编程中主要围绕着三个特性实现。 可见性 可见性是指当多个线程访问同一个共享变量时,一个线程修改了这个变量的值,其他线程能够立即看到修改后的值。 原子性 原子性指的一个...
  • C语言中volatile关键字作用

    千次阅读 2020-11-08 09:16:04
    volatile关键字 一.前言  编译器优化介绍: 由于内存访问速度远不及CPU处理速度,为提高机器整体性能, 1)在硬件上: 引入硬件高速缓存Cache,加速对内存的访问。另外在现代CPU中指令的执行并不一定严格按照顺序...
  • volatile关键字作用及使用场景

    千次阅读 2020-02-16 22:29:19
    volatile关键字是java虚拟机提供的最轻量级的同步机制。在并发的场景下,我们都习惯于使用synchronized锁进行同步...下面就来简单叙述一下volatile关键字作用,及其适用场景。 一、volatile的特性 被volatile修饰...
  • Volatile Volatile : (意思是 不稳定的)限定一个对象可被外部进程(操作系统、硬件或并发线程等)改变,声明时的语法如下: int volatile nVint; 这个说明 让程序每次读取nVint 真正的值。 volatile int i=10; ...
  • Java中的volatile关键字作用和底层原理
  • 浅析Java中volatile关键字及其作用

    万次阅读 2018-06-26 23:25:15
    volatile 关键字作用 内存可见性 禁止指令重排 1、多线程 (1)进程和线程 进程:一个正在执行中的程序, 动态的 ,是系统进行资源分配和调度的独立单位。 线程:进程中一个独立的控制单元,线程控制着进程的执行。...
  • Java中的volatile关键字的功能volatile是java中的一个类型修饰符。它是被设计用来修饰被不同线程访问和修改的变量。如果不加入volatile,基本上会导致这样的结果:要么无法编写多线程程序,要么编译器 失去大量优化...
  • C++中volatile关键字作用

    千次阅读 2019-06-01 15:18:24
    对于较官方的解释是:volatile作为指令关键字,确保本条指令不会因编译器的优化而被省略,即系统每次从变量所在内存读取数据而不是从寄存器读取备份。 下面将进行详细说明: 易变性 编译器对volatile修饰的变量,当...
  • 深入理解volatile关键字作用

    千次阅读 2018-07-30 17:41:29
    Java并发编程学习笔记 深入理解volatile关键字作用 引言:以前只是看过介绍volatile的文章,对其的理解也只是停留在理论的层面上,由于最近在项目当中用到了关于并发方面的技术,所以下定决心深入研究一下java...
  • 关于C语言中volatile 关键字的使用纸上得来终觉浅,绝知此事要躬行!中国五千年文化,古人爷爷们诚不欺我,今天算是又体验了一回。起因是这样的:先上一张图,图中Req_Timer是我定义的一个变量,uint16_t Req_Timer,...
  • volatile修饰符在C语言中的用法本文章将讨论volatile这个修饰符在...volatile关键字告诉编译器,这个变量可能在任何时刻都会被改变。有时变量的改变对编译器来说有点“隐蔽”,也许就是这种隐蔽让编译给我们的程...
  • 文章目录Java内存模型中的三个特性关键字volatile的特殊规则保证该变量对所有线程的可见性。禁止指令重排序。Volatile内存原理Volatile性能拓展:使用AtomicInteger改善上面的变量自增运算测试程序 Java内存模型中...
  • 主要给大家介绍了关于C++中volatile关键字及常见的误解的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • ``` public class testVolatile { private int i = 0; // a线程调用 public void foo1() { ...求高人指点,变量 i 没有增加 volatile 关键字时,第二个输出为什么会随着第一个i 的变化而变化?
  • volatile关键字作用和简介 介绍: – volatile是java最轻量级的同步机制。 特性: 可见性:变量的读取直接访问内存而不是cpu 缓存。当一个线程修改了volatile修饰的变量之后,无论是否加锁,其他线程都能立即看到...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 125,075
精华内容 50,030
关键字:

volatile关键字的作用