Java Volatile关键字可见性问题分析

  • Java 内容模型
    • 普通变量(非Vola变量)的内存不可见性
    • Volatile变量的内存可见性
    • 剩余疑惑

Java 内容模型

具体可以查看这篇文章Java内存模型,大致就是,在Java多线程工作中,每个线程有自己的工作内存,变量存在主内存,在Java线程读取变量的时候,会优先在自己的工作内存中查找,当工作内存中不存在时,会通过Load操作进行读取变量,当对数据发生修改时会通过Save将变量更新到主内存中,而为了保证内存的可见性,可以通过Volatile关键字修饰变量,通过关键字修饰后的变量,在被一个线程更改后,新的值会对其他的线程立即得知。听起来是那么回事,但是自己理解的时候,用多线程发现有时候好像又不是那回事,好像普通变量也会在一个线程更新值的时候,对别的线程也会进行更新,这个问题目前没有解决还需要,继续了解Save和Load的时机。

普通变量(非Vola变量)的内存不可见性

package LockFuncs;public class VolatileTest {boolean  isStop = false;public void test(int i){Thread t1 = new Thread(){public void run() {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}isStop=true;System.out.println(isStop);}};Thread t2 =  new Thread(){public void run() {while (!isStop) {}}};t2.start();t1.start();}public static void main(String args[]) throws InterruptedException {for (int i =0;i<1;i++){new VolatileTest().test(i);}}
}

运行结果:线程1通过先sleep,让线程2先读取到isStop的值为false,此时线程2会一直死循环中,当sleep结束后,线程1被唤醒,更改isStop=true,此时如果具有可见性,则线程1应该会立即感知isStop为true,结束死循环,但是通过结果可见,线程2仍然处于死循环中,表明此时isStop仍为false,可以知道普通变量不具有可见性,每次读取仍是从工作内存中获取的值。

Volatile变量的内存可见性


public class VolatileTest {volatile boolean  isStop = false;public void test(int i){Thread t1 = new Thread(){public void run() {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}isStop=true;System.out.println(isStop);}};Thread t2 =  new Thread(){public void run() {while (!isStop) {}}};t2.start();t1.start();}public static void main(String args[]) throws InterruptedException {for (int i =0;i<20;i++){new VolatileTest().test(i);}}
}

运行结果:通过对isStop添加volatile关键字,可见每次循环时,更改isStop的值,死循环都会结束,可知变更volatile时,对于线程2是可见的。

剩余疑惑

System.out.println(isStop);这句话是一个原子操作,因为在方法内部使用了synchronized关键字实现了同步锁,不知道是不是这个原因,导致在执行这个操作会更发生一次工作内存和主内存的交互,导致值会更新。

package LockFuncs;public class VolatileTest {boolean  isStop = false;public void test(int i){Thread t1 = new Thread(){public void run() {//                try {//                    Thread.sleep(1000);
//                } catch (InterruptedException e) {//                    e.printStackTrace();
//                }isStop=true;System.out.println(isStop);}};Thread t2 =  new Thread(){public void run() {while (!isStop) {System.out.println(isStop);}}};t2.start();t1.start();}public static void main(String args[]) throws InterruptedException {for (int i =0;i<250;i++){new VolatileTest().test(i);}}
}

运行结果:不会产生死循环,直到执行结束。

package LockFuncs;public class VolatileTest {boolean  isStop = false;public void test(int i){Thread t1 = new Thread(){public void run() {//                try {//                    Thread.sleep(1000);
//                } catch (InterruptedException e) {//                    e.printStackTrace();
//                }isStop=true;System.out.println(isStop);}};Thread t2 =  new Thread(){public void run() {while (!isStop) {//                    System.out.println(isStop);}}};t2.start();t1.start();}public static void main(String args[]) throws InterruptedException {for (int i =0;i<250;i++){new VolatileTest().test(i);}}
}

运行结果:通过将线程2中的打印注释后,运行结果就会出现死循环。

Java Volatile关键字可见性问题分析相关推荐

  1. Java volatile关键字原理解剖

    Java volatile关键字原理解剖 文章目录 Java volatile关键字原理解剖 参考文章 前置知识 CPU缓存模型 CPU缓存行 并发编程基本概念 Java锁概念 volatile关键字 ...

  2. [Java并发编程(三)] Java volatile 关键字介绍

    [Java并发编程(三)] Java volatile 关键字介绍 摘要 Java volatile 关键字是用来标记 Java 变量,并表示变量 "存储于主内存中" .更准确的说 ...

  3. Java volatile关键字详解

    1.关于volatile volatile是Java语言中的关键字,用来修饰会被多线程访问的共享变量,是JVM提供的轻量级的同步机制,相比同步代码块或者重入锁有更好的性能.它主要有两重语义,一是保证多 ...

  4. Java——volatile关键字详解

    关注微信公众号:CodingTechWork,一起学习进步. volatile介绍 volatile概述 volatile是比synchronized关键字更轻量级的同步机制,访问volatile变量 ...

  5. java volatile关键字的作用_java volatile关键字作用及使用场景详解

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

  6. volite java_如何理解 JAVA volatile 关键字

    最近在重新梳理多线程,同步相关的知识点.关于 volatile 关键字阅读了好多博客文章,发现质量高适合小白的不多,最终找到一篇英文的非常通俗易懂.所以学习过程中顺手翻译下来,一方面巩固知识,一方面希 ...

  7. Java volatile关键字总结

    JMM(为什么需要volatile) Java内存模型(JavaMemoryModel)描述了Java程序中各种变量(线程共享变量)的访问规则,以及在JVM中将变量,存储到内存和从内存中读取变量这样的 ...

  8. java volatile关键字使用

    1.为什么要使用volatile关键字? 先看下面的代码: //线程1 boolean stop = false; while(!stop){doSomething(); }//线程2 stop = ...

  9. 一个具体的例子学习Java volatile关键字

    相信大多数Java程序员都学习过volatile这个关键字的用法.百度百科上对volatile的定义: volatile是一个类型修饰符(type specifier),被设计用来修饰被不同线程访问和 ...

最新文章

  1. Nginx PHP 报504 Gateway time-out错误的解决方法
  2. 接口隔离原则最直白描述
  3. 【从蛋壳到满天飞】JS 数据结构解析和算法实现-哈希表
  4. [CF917D]Stranger Trees[矩阵树定理+解线性方程组]
  5. 【转】探索c#之Async、Await剖析
  6. numpy使用where函数定位满足条件的下标
  7. Qt5学习笔记之bin文件合成工具四:完善功能打包程序
  8. ubuntu开机时出现“waiting for network configuration” 问题的解决
  9. android--显式跳转和隐式跳转
  10. mysql数据库——思维导图
  11. JAVA面试宝典2018-2019
  12. 《数据结构》天勤和王道 第五章 树
  13. 美团监控系统mysql_美团MySQL数据库巡检系统的设计与应用
  14. 电子计算机主机房国标,中华人民共和国国家标准电子计算机机房设计规范
  15. 高级电工实验室成套设备(带功率表、功率因数表)
  16. 免费的银行联行号查询/接口
  17. 「消息秒回」是一种美德
  18. jsp+struct标签实现分页(只有jsp代码),内用到迭代标签、if标签、bean
  19. ESP8266作为服务器配置方法
  20. ssm毕设项目高校教师科研能力评定系统40n60(java+VUE+Mybatis+Maven+Mysql+sprnig)

热门文章

  1. TM4C USB-HID了解学习(二)
  2. 微信小程序常用文档地址(自用常更新)
  3. vivo适配android10,完整升级安卓10教程!华为小米OV一加8余款机型率先适配安卓Q...
  4. 使用Hist函数实现图像直方图
  5. ai钢笔工具怎么描线_AI钢笔如何绘制生动轮廓线(在AI软件中,如何用钢笔工具绘制出有生动轮廓线的图形?)...
  6. 电子电路图中VCC、IO、3V3OUT、VDD3V3解释
  7. 中南大学计算机导师名单,中南大学信息学院导师一览表.pdf
  8. 关于AD转换设计的一些经验总结(转载)
  9. Springboot中使用ResponseBodyAdvice对异常,分页等请求进行封装
  10. 日常办公实用网站整理