volatile是java虚拟机提供的轻量级的同步机制

JMM(Java内存模型)是围绕着并发编程中原子性、可见性、有序性这三个特征来建立的

原子性:一个操作或多个操作要么全部执行完成且执行过程不被中断,要么就不执行。

可见性:当多个线程同时访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。

有序性:程序执行的顺序按照代码的先后顺序执行。

volatile保证了可见性,有序性,不保证原子性

证明可见性的代码:

 package concurrent;

 import java.util.concurrent.TimeUnit;

 /*
* @description: volatile特性
* @date 2019.04.22 20:48
*/
//数据类
class Mydata{ volatile int num = 0; public void changeNum(){
this.num = 100;
}
} public class VolatileDemo { public static void main(String[] args) throws InterruptedException{
Mydata mydata = new Mydata();
new Thread(() -> {
System.out.println("===="+Thread.currentThread().getName() +"线程启动===");
//暂停3秒
try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) {}
//3秒后t1线程改变num的值
mydata.changeNum();
System.out.println(Thread.currentThread().getName()+"线程将num的值改为"+mydata.num);
},"t1").start(); //num的值不变就一直循环
long begin = System.currentTimeMillis();
while (mydata.num == 0){
//num如果不被volatile修饰会一直循环
}
long cost = System.currentTimeMillis() - begin;
System.out.printf(Thread.currentThread().getName()+"线程检测到num的值已经改变,cost{%d},证明了volatile的可见性",cost);
}
}

运行结果为:

====t1线程启动===
t1线程将num的值改为100
main线程检测到num的值已经改变,cost{3001},证明了volatile的可见性

  

证明不保证原子性的代码:

class Mydata{

    volatile int num = 0;

    public void changeNum(){
this.num = 100;
} public void numIncreOne(){
this.num++;
}
} public class VolatileDemo { public static void main(String[] args) throws InterruptedException{ Mydata mydata = new Mydata();
//开启10个线程每个线程调用1000次num++
for (int i = 0; i < 10; i++) {
new Thread(() -> {
for (int j = 0; j < 1000; j++) {
mydata.numIncreOne();
}
},String.valueOf(i)).start();
} //输出num的值,如果volatile能保证原子性num将等于10000
System.out.println(mydata.num);
System.out.println(mydata.num ==10000?"volatile可以保证原子性":"volatile无法保证原子性");
}
}

输出结果:

5856
volatile无法保证原子性

多线程环境中,线程交替执行,编译器会通过对指定进行重排序来进行优化。被volatile修饰的变量不会参与重排序,保证有序性。

证明有序性的代码:

     int num = 0;

     private boolean flag = false;

     private void reSort1(){
num = 1; //语句1
flag = true; //语句2
} private void reSort2(){
if(flag){
num++;
System.out.println("num的值为"+num);
}
}
多线程情况下有可能先执行语句2,再执行语句1,从而导致num只自增1次,输出为1。

volatile关键字的特性及证明的更多相关文章

  1. volatile关键字的特性总结

    当一个变量定义为volatile后,它将具备两个特性: 1.保证此变量对所有线程的可见性,所谓"可见性",,是指当一个线程修改了这个变量的值,新值对于其他线程来说是可以立即得知的. ...

  2. 你真的了解volatile关键字吗?

    volatile关键字经常在并发编程中使用,其特性是保证可见性以及有序性,但是关于volatile的使用仍然要小心,这需要明白volatile关键字的特性及实现的原理,这也是本篇文章的主要内容. 一. ...

  3. Java面试官最爱问的volatile关键字

    在Java的面试当中,面试官最爱问的就是volatile关键字相关的问题.经过多次面试之后,你是否思考过,为什么他们那么爱问volatile关键字相关的问题?而对于你,如果作为面试官,是否也会考虑采用 ...

  4. 面试中的volatile关键字

    在Java的面试当中,面试官最爱问的就是volatile关键字相关的内容.经过多次面试之后,你是否思考过,为什么他们那么爱问volatile关键字相关的问题?而对于你,如果作为面试官,是否也会考虑采用 ...

  5. JUC 并发编程--05, Volatile关键字特性: 可见性, 不保证原子性,禁止指令重排, 代码证明过程. CAS了解么 , ABA怎么解决, 手写自旋锁和死锁

    问: 了解volatile关键字么? 答: 他是java 的关键字, 保证可见性, 不保证原子性, 禁止指令重排 问: 你说的这三个特性, 能写代码证明么? 答: .... 问: 听说过 CAS么 他 ...

  6. Java单例模式和volatile关键字

    单例模式是最简单的设计模式,实现也非常"简单".一直以为我写没有问题,直到被 Coverity 打脸. 1. 暴露问题 前段时间,有段代码被 Coverity 警告了,简化一下代码 ...

  7. 线程安全(上)--彻底搞懂volatile关键字

    对于volatile这个关键字,相信很多朋友都听说过,甚至使用过,这个关键字虽然字面上理解起来比较简单,但是要用好起来却不是一件容易的事.这篇文章将从多个方面来讲解volatile,让你对它更加理解. ...

  8. volatile关键字学习

    volatile关键字在实际工作中我用的比较少,可能因为我并不是造轮子的.但是用的少不是你不掌握的借口,还是要创造场景去使用这个关键字,本文将会提供丰富的demo. volatile 发音:英[ˈvɒ ...

  9. C# volatile 关键字

    volatile 就像大家更熟悉的const一样,volatile是一个类型修饰符(type specifier).它是被设计用来修饰被不同线程访问和修改的变量.如果不加入volatile,基本上会导 ...

随机推荐

  1. IP地址和MAC地址的关系

    IP地址是网络层的概念,而MAC地址是数据链路层的概念.IP地址在网络层上对不同的硬件地址类型进行了统一,从而提供网络互联的可能:而硬件地址在真正的数据传输中要用到.当应用程序把数据从源主机发送到目标 ...

  2. JavaScript单线程和异步机制

    随着对JavaScript学习的深入和实践经验的积累,一些原理和底层的东西也开始逐渐了解.早先也看过一些关于js单线程和事件循环的文章,不过当时看的似懂非懂,只留了一个大概的印象:浏览器中的js程序时 ...

  3. Java 读书笔记 (十三) for each 循环

    JDK 1.5引进了一种新的循环类型,被称为foreach循环或者加强型循环,它能在不使用下标的情况下遍历数组. 实例: public class TestArray{ public static v ...

  4. 基于 HTML5 OpenLayers3 实现 GIS 电信资源管理系统

    前言 通过结合 HTML5 和 OpenLayers 可以组合成非常棒的一个电信地图网络拓扑图的应用,形成的效果可以用来作为电信资源管理系统,美食定位分享软件,片区找房,绘制铁轨线路等等,各个领域都能 ...

  5. indexer.go

    package) ; , ].DocId,:],)) :],) :], , ] ; ];]--],]) , ) )) )-b+b*d/avgDocLength)) , ;].locations[ind ...

  6. I/O------字节输出流

    package io.day03; import java.io.FileOutputStream; import java.io.OutputStream; public class day03ou ...

  7. dqname_widnows.go

    package nsqd // On Windows, file names cannot contain colons. func getBackendName(topicName, channel ...

  8. 【codeforces 516B】Drazil and Tiles

    题目链接: http://codeforces.com/problemset/problem/516/B 题解: 首先可以得到一个以‘.’为点的无向图,当存在一个点没有边时,无解.然后如果这个图边双联 ...

  9. bzoj4871 [Heoi2017]摧毁“树状图”

    刷完了去年的省选题,发现自己dp已经凉凉了. 虽然暴力可以拿到80分的好成绩,但是正解的dp状态和转移还是没能想到,是时候补一波dp了 这道题我们肯定是要树形dp,存的肯定就是子树某种状态的最多的联通 ...

  10. USACO JAN14 奶牛冰壶运动 凸包+判定

    满足条件的一定是在凸包内的,直接判断 恬不知耻的加了特判,2333 #include<cstdio> #include<iostream> #include<cstrin ...