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,基本上会导 ...
随机推荐
- How to untar a TAR file using Apache Commons
import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress ...
- datetime日期和时间
datetime是Python处理日期和时间的标准库. from datetime import datetime # 获取当前时间 now = datetime.now() print(now) # ...
- 玩转JPA(一)---异常:Repeated column in mapping for entity/should be mapped with insert="false" update="fal
最近用JPA遇到这样一个问题:Repeated column in mapping for entity: com.ketayao.security.entity.main.User column: ...
- map用法
描述: map()会根据提供的参数对指定序列做映射. 语法: map(function,iterable) function:函数以参数列表中的每一个元素调用function函数,返回包含每次func ...
- python3[爬虫实战] 使用selenium,xpath爬取京东手机
使用selenium ,可能感觉用的并不是很深刻吧,可能是用scrapy用多了的缘故吧.不过selenium确实强大,很多反爬虫的都可以用selenium来解决掉吧. 思路: 入口: 关键字搜索入口 ...
- celery学习笔记2
1.定义: Celery是一个异步的任务队列(也叫做分布式任务队列) 2.工作结构 Celery分为3个部分 (1)worker部分负责任务的处理,即工作进程(我的理解工作进程就是你写的python代 ...
- Python三元运算
result = 值1 if 条件 else 值2 如果条件为真,result = 值1 如果条件为假, result = 值2.
- kcp-go源码解析
概念 ARQ:自动重传请求(Automatic Repeat-reQuest,ARQ)是OSI模型中数据链路层的错误纠正协议之一.RTO:Retransmission TimeOutFEC:Forwa ...
- 「LOJ 2289」「THUWC 2017」在美妙的数学王国中畅游——LCT&泰勒展开
题目大意: 传送门 给一个动态树,每个节点上维护一个函数为$f(x)=sin(ax+b)$.$f(x)=e^{ax+b}$.$f(x)=ax+b$中的一个. 支持删边连边,修改节点上函数的操作. 每次 ...
- 【BZOJ 3924】[Zjoi2015]幻想乡战略游戏
题目: 题解: 对点分树理解加深了233,膜拜zzh干翻紫荆花. 感谢zzh的讲解. 首先优化基于传统DP,假设树不发生变化,我们就可以利用DP求出带权重心. 考虑修改,我们思路不变,还是从root开 ...