Volatile关键字实现原理

1、认识volatile关键字

程序举例

用一个线程读数据,一个线程改数据

存在数据的不一致性

2、机器硬件CPU与JMM

(1)CPU Cache模

(2)CPU缓存的一致性问题

解决方案:

1)总线加锁(粒度太大)

2)MESI()

  1. 读操作:不做任何事情,把Cache中的数据读到寄存器
  2. 写操作:发出信号通知其他的CPU讲改变量的Cache line置为无效,其他的CPU要访问这个变量的时候,只能从内存中获取。

Cache line  CPU的cache中会增加很多的Cache line

(3)Java内存模型

1)         主存中的数据所有线程都可以访问(共享数据)

2)         每个线程都有自己的工作空间,(本地内存)(私有数据)

3)         工作空间数据:局部变量、内存的副本

4)         线程不能直接修改内存中的数据,只能读到工作空间来修改,修改完成后刷新到内存

3、Volatile关键字的语义分析

volatile作用:让其他线程能够马上感知到某一线程多某个变量的修改

(1)保证可见性

对共享变量的修改,其他的线程马上能感知到

不能保证原子性  读、写、(i++)

(2)保证有序性

重排序(编译阶段、指令优化阶段)

输入程序的代码顺序并不是实际执行的顺序

重排序后对单线程没有影响,对多线程有影响

Volatile

Happens-before

volatile规则:

对于volatile修饰的变量:

(1)volatile之前的代码不能调整到他的后面

(2)volatile之后的代码不能调整到他的前面(as if seria)

(3)霸道(位置不变化)

Int i=0;

Int a=3;

Int b=5;

Volatile Int j=3;

Int i=0;

Int a=3;

Int b=5;

Int m=i+j;

I++;

J++;

(3)volatile的原理和实现机制(锁、轻量级)

HSDIS   --反编译---汇编

Java --class---JVM---》ASM文件

Volatile  int  a ;

Lock :a

4、Volatile的使用场景

(1)状态标志(开关模式)

public class ShutDowsnDemmo extends Thread{
private volatile boolean started=false; @Override
public void run() {
while(started){
dowork();
}
}
public void shutdown(){
started=false;
}
}

  

(2)双重检查锁定(double-checked-locking)

DCL(7)

public class Singleton {

    private volatile static Singleton instance;

    public static Singleton getInstance(){

        if(instance==null){

            synchronized (Singleton.class){

                instance=new Singleton();

            }

        }

        return instance;

    }

}

  

(3)需要利用顺序性

5、volatile与synchronized的区别

(1)使用上的区别

Volatile只能修饰变量,synchronized只能修饰方法和语句块

(2)对原子性的保证

synchronized可以保证原子性,Volatile不能保证原子性

(3)对可见性的保证

都可以保证可见性,但实现原理不同

Volatile对变量加了lock,synchronized使用monitorEnter和monitorexit  monitor  JVM

(4)对有序性的保证

Volatile能保证有序,synchronized可以保证有序性,但是代价(重量级)并发退化到串行

(5)其他

synchronized引起阻塞

Volatile不会引起阻塞

小程序:

最新文章

  1. UML用例图(转载)
  2. REST简介及设计原则
  3. Java解惑七:很多其它类之谜
  4. UiAutomator源码分析之获取控件信息
  5. makefile讲解
  6. SpringBoot配置(1) 配置文件application&yml
  7. Python函数——命名空间与闭包
  8. break和continue语句(初学者)
  9. 菜鸟学Java(二十三)——Java内存分析
  10. ArrayBlcokingQueue,LinkedBlockingQueue与Disruptor三种队列对比与分析
  11. Android Studio 错误: 非法字符: '\ufeff' 解决方式|错误: 须要class, interface或enum
  12. spring应用中多次读取http post方法中的流(附源码)
  13. 九数组分数|2015年蓝桥杯B组题解析第五题-fishers
  14. css 超出部分以省略号的形式显示
  15. IIC通讯程序
  16. (转)ReentrantLock与Synchronized同步区别
  17. 环境变量PATH超长问题[转]
  18. Java中的HashMap
  19. C++中substr的用法
  20. [LeetCode] Restore IP Addresses 回溯

热门文章

  1. USACO 5.4 tour的dp解法
  2. OkHttp解析
  3. SpringBoot整合Ribbon注入RestTemplate实例找不到原因
  4. Go语言中的代码重用 - 继承还是组合?
  5. Android Studio:layout-sw600dp文件夹中创建activity_main.xml
  6. 704. Binary Search
  7. Mantis优化改造(功能篇)
  8. Qt容器类之二:迭代器
  9. h5-21-文件操作-读取文件内容
  10. Myisamchk使用