volatile关键字的特性及证明
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关键字的特性及证明的更多相关文章
- volatile关键字的特性总结
当一个变量定义为volatile后,它将具备两个特性: 1.保证此变量对所有线程的可见性,所谓"可见性",,是指当一个线程修改了这个变量的值,新值对于其他线程来说是可以立即得知的. ...
- 你真的了解volatile关键字吗?
volatile关键字经常在并发编程中使用,其特性是保证可见性以及有序性,但是关于volatile的使用仍然要小心,这需要明白volatile关键字的特性及实现的原理,这也是本篇文章的主要内容. 一. ...
- Java面试官最爱问的volatile关键字
在Java的面试当中,面试官最爱问的就是volatile关键字相关的问题.经过多次面试之后,你是否思考过,为什么他们那么爱问volatile关键字相关的问题?而对于你,如果作为面试官,是否也会考虑采用 ...
- 面试中的volatile关键字
在Java的面试当中,面试官最爱问的就是volatile关键字相关的内容.经过多次面试之后,你是否思考过,为什么他们那么爱问volatile关键字相关的问题?而对于你,如果作为面试官,是否也会考虑采用 ...
- JUC 并发编程--05, Volatile关键字特性: 可见性, 不保证原子性,禁止指令重排, 代码证明过程. CAS了解么 , ABA怎么解决, 手写自旋锁和死锁
问: 了解volatile关键字么? 答: 他是java 的关键字, 保证可见性, 不保证原子性, 禁止指令重排 问: 你说的这三个特性, 能写代码证明么? 答: .... 问: 听说过 CAS么 他 ...
- Java单例模式和volatile关键字
单例模式是最简单的设计模式,实现也非常"简单".一直以为我写没有问题,直到被 Coverity 打脸. 1. 暴露问题 前段时间,有段代码被 Coverity 警告了,简化一下代码 ...
- 线程安全(上)--彻底搞懂volatile关键字
对于volatile这个关键字,相信很多朋友都听说过,甚至使用过,这个关键字虽然字面上理解起来比较简单,但是要用好起来却不是一件容易的事.这篇文章将从多个方面来讲解volatile,让你对它更加理解. ...
- volatile关键字学习
volatile关键字在实际工作中我用的比较少,可能因为我并不是造轮子的.但是用的少不是你不掌握的借口,还是要创造场景去使用这个关键字,本文将会提供丰富的demo. volatile 发音:英[ˈvɒ ...
- C# volatile 关键字
volatile 就像大家更熟悉的const一样,volatile是一个类型修饰符(type specifier).它是被设计用来修饰被不同线程访问和修改的变量.如果不加入volatile,基本上会导 ...
随机推荐
- Step by step guide to set up master and slave machines on Windows
Note: There is no need to install Jenkins on the slave machine. On your master machine go to Manage ...
- selenium中浏览器及对应的驱动(可下载)
https://blog.csdn.net/huilan_same/article/details/52615123,灰蓝大神的总结,可直接下载 下载chrome浏览器,查看版本 http://blo ...
- Django+Bootstrap+Mysql 搭建个人博客(六)
6.1.comments插件 (1)安装 pip install django-contrib-comments (02)settings INSTALLED_APPS = [ 'django.con ...
- Asp.Net WebAPI中Filter过滤器的使用以及执行顺序
转发自:http://www.cnblogs.com/UliiAn/p/5402146.html 在WEB Api中,引入了面向切面编程(AOP)的思想,在某些特定的位置可以插入特定的Filter进行 ...
- noip前集训
10.18 关网了,2333 上午考试,130 rank16 一直在刚T2的割点,却直接弃了一道第一眼看上去不可做但实际并没那么难想的小模拟 但是T2没搞出来是不是也要反思一下,先是割点板子忘了,之后 ...
- bzoj 1098 poi2007 办公楼 bfs+链表
题意很好理解,求给出图反图的联通块个数. 考虑这样一个事情:一个联通块里的点,最多只会被遍历一次,再遍历时没有任何意义 所以用链表来存,每遍历到一个点就将该点删掉 #include<cstdio ...
- BZOJ_3011_[Usaco2012 Dec]Running Away From the Barn _可并堆
BZOJ_3011_[Usaco2012 Dec]Running Away From the Barn _可并堆 Description 给出以1号点为根的一棵有根树,问每个点的子树中与它距离小于l的 ...
- [NOIP2016]愤怒的小鸟 D2 T3
Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可以用它向第一象限发射一只红色的小鸟,小鸟们的 ...
- gitlab-ci-runner安装
前言 什么是CI/CD? CI (Continuous Integration) 持续集成, CD (Continuous Delivery) 持续部署 个人理解 本地开发代码, 提交远程仓库 仓库接 ...
- 使用limit查询的同时取得总的记录数:SQL_CALC_FOUND_ROWS和FOUND_ROWS()
通常我们都用如下的sql来进行列表 SELECT COUNT(*) FROM users WHERE name LIKE 'a%';SELECT name, email FROM users WHER ...