zoukankan      html  css  js  c++  java
  • java vloatile 关键字

    java中volatile关键字的使用涉及到java的内存模型,JMM。简单来说,每个线程都有一个本地内存(虚拟的),线程共享的变量存储在主内存中,主内存在堆中。内存访问方式如下图所示。

    volatile的作用总结如下:

    (1)可见性:对一个volatile变量的读取,总是能够看到(任意线程)对这个变量的最后写入,即能够读到最新的值。

    (2)原子性:针对vloatile基本类型(包括long double int等等)变量的读/写c操作具有原子性,但是复合操作不具有原子性。

    原子性操作的定义:原子性操作指的是一旦操作开始,就不能被线程调度中断,直到该原子操作执行完毕才会发生线程切换,所以不可分的原子操作就可以避免线程竞争,因此可以代替同步。但是除非是专家,一般我们都应该使用同步而不是原子操作。

    注意:对出long和double外的其他基本数据类型的读写操作都是原子性操作。但是JVM会将64位的long和double类型数据分开两个32为数据来进行读写操作,所以在读取或者写入中间会发生线程切换,从而导致数据破坏。因此需要在前面加上volatile关键字就可以保证long和double的存取也是原子性操作(atomic operation)。

      最后,什么时候使用volatile关键字呢?基本上,如果一个域可能被多个线程同时访问,并且这些线程中至少有一个是有对这个域做写操作的,那么就要把这个域设置为volatile的,  如果一个共享变量会被多个线程同时访问,那么使用volatile关键字可以保证数据的可视性,也就是在一个线程中更改了volatile类型域后,会立刻刷新主内存,其他线程读的时候读到的就是最新被修改的值。但是如果一个域已经完全由synchronized方法或者语句块保护,那么就不需要设置成volatile了,因为synchronized方法也会导致主内存的刷新。再次说明的是,第一选择应该是使用synchronized关键字,其他的方法都是有风险的。volatile的最主要作用是实现了多个线程之间数据的可视性。

      

    上述图中的操作过程描述

    (1)线程A写:线程A中更新了N的值,flag的值,对N的更新只是在本地内存中,但是对flag写入后,因为flag是volatile的,所以会导致本地内存A中被线程A更新过的两个共享变量被刷新到了主内存中,这样保证主内存中保存的是volatile型变量最新被写入的值。

    (2)线程B读:线程B读volatile类型的变量时,JMM会把本地内存置为无效,线程接下来将从主内存中读取共享变量。这样保证读取的是主内存中最新的值。

  • 相关阅读:
    Android Gradle Plugin指南(五)——Build Variants(构建变种版本号)
    文件内容操作篇clearerr fclose fdopen feof fflush fgetc fgets fileno fopen fputc fputs fread freopen fseek ftell fwrite getc getchar gets
    文件操作篇 close creat dup dup2 fcntl flock fsync lseek mkstemp open read sync write
    嵌入式linux应用程序调试方法
    version control system:git/hg/subversion/cvs/clearcase/vss。software configruation management。代码集成CI:Cruisecontrol/hudson/buildbot
    最值得你所关注的10个C语言开源项目
    如何记录linux终端下的操作日志
    CentOS 5.5 虚拟机安装 VirtualBox 客户端增强功能
    sizeof, strlen区别
    C/C++嵌入式开发面试题
  • 原文地址:https://www.cnblogs.com/wll-zju/p/4337839.html
Copyright © 2011-2022 走看看