关于volatile的使用
来源:互联网 发布:apache python 编辑:程序博客网 时间:2024/05/11 23:08
一、论点
第一层 保证原子性,针对64位变量的多线程操作能保证一次操作都是64位
第二层 保证了顺序一致性,不参与重排序在新的内存模型下
第三层 保证了可见性(可见性仅仅对于基本变量,如果是引用变量只能保证在赋值引用的那一刻,如果赋值后其他线程操作这个引用的变量对象 还是不能保证可见性)
二、程序说明
1. 保证原子性
publicclass Ano {
privatestaticlongnum = Long.MAX_VALUE;
publicstaticvoid main(String[] args) {
System.out.println(Long.MAX_VALUE);
System.out.println(Long.MIN_VALUE);
new Thread(){
publicvoid run(){
while(true){
long l =num;
if(l==Long.MAX_VALUE){
num = Long.MIN_VALUE;
}else{
num = Long.MAX_VALUE;
}
}
}
}.start();
new Thread(){
publicvoid run(){
while(true){
long l =num;
if(l!=Long.MAX_VALUE && l!=Long.MIN_VALUE){
System.out.println(l);
return;
}
}
}
}.start();
}
}
运行结果:
9223372036854775807
-9223372036854775808
-9223372032559808513
结论:为什么会有第三个输出呢?jvm操作内存时jvm是32位时写入数据的时候最小单位是32位,如果jvm是64位,最小操作单位就是64位。在没锁的情况下,一个线程写入64位,是分2次写的,先写高32位 在写低32位,如果刚好第一个线程在写高32位的时候 另外的线程读取这个long值,就会出错,就会读到最新的高32位,和之前老数据的低32位,就是错的的值了。所以就会出现第三个输出值。
这样就不会有问题了:privatestaticvolatilelongnum = Long.MAX_VALUE;
2. 保证了顺序一致性,不参与重排序在新的内存模型下
publicclass A {
privatestatic A a;
privateintx = 1;
privateinty = 2;
public A(int x,int y){
this.x = x;
this.y = y;
}
publicstatic A getInstance(){
if(a==null){
synchronized (A.class) {
if(a==null){
a =new A(3,4);
}
}
}
returna;
}
}
结论:第一个线程获取到a对象看到a的x是3,a的y是4, 但是如果刚好第二个线程访问,
在判断if(a==null)的时候,看到的是a不是null就获取了a对象,但是这个a对象可能还在构造,此时获取到a的时候看到的x还是1或者y还是2,这样的值就是过期的值,这就是重排序。
改成privatestaticvolatile Aa;就不会有这个问题了!
3. 保证了可见性
publicclass A {
publicstaticvolatilebooleanb = false;
publicstaticintx = 1;
publicstaticvoid main(String[] args) {
new Thread() {
publicvoid run() {
boolean bb =b;
if (bb) {
System.out.println(x);
}
}
}.start();
x = 2;
b =true;
}
}
结论:X的输出值一定是2!但是如果b不是volatile则不一定,因为底层执行的情况是,main线程先把b=true写入到了内存,再把x=2写入内存的,每个线程有一个工作区间 也就是缓存区间,用来缓存数据,假如b=true先从线程缓存同步到主存,此时x=2还没有同步到主存,其他线程看到的x就是1了。加上volatile,则当b=true执行后,就会吧b=true,x=2都从缓存同步到主存中,这样x就肯定是2了。
- 关于volatile的使用
- 关于volatile的使用
- 关于volatile的使用
- 关于volatile的变量
- 关于volatile的用法
- 关于volatile的用法
- 关于volatile的用法
- [转载]关于native,transient,volatile,synchronized四个关键字的使用
- 关于native,transient,volatile,synchronized四个关键字的使用
- 关于native,transient,volatile,synchronized四个关键字的使用
- volatile的使用
- volatile的使用
- const volatile的使用
- volatile的使用
- volatile的使用
- volatile关键字的使用
- 使用volatile的例子
- volatile的使用
- HDU 2181 哈密顿绕行世界问题
- Linux下/proc目录简介
- java 获得WebContent的绝对路径
- 学习ios(必看经典)牛人40天精通iOS开发的学习方法
- jQuery 遍历 - 祖先
- 关于volatile的使用
- Android Launcher分析和修改4——初始化加载数据
- Http 协议的缓存(二)
- 在使用grunt进行压缩js时候,如何处理文件里名称面有多个点号?
- ARCGIS engine 定长且批量绘制线段的中垂线
- 树状数组:第K大值
- 单例模式-c++
- my vc6 program - brownian motion articles simulation
- PKU 2356 Find a multiple