Volatile

2018-12-27  本文已影响0人  程序设计法师

volatile只能修饰类变量和实例变量,对于方法参数,局部变量,实例变量,类常量都不能修饰
我们的主内存(RAM)(一共有三级缓存,L3 cache速度最快,依次降低)的读写速度远远落后于CPU cache,Cache的出现是为了解决cpu直接访问内存效率低下问题的,程序在运行过程中,会将运算所需要的数据从主存复制一份到CPU cache中,这样CPU进行计算时就可以直接对CPU cache中的数据进行读取和写入,当运算结束之后,再将CPU cache中的最新数据刷新到主内存中,CPU通过直接访问cache的方式替代直接访问主存的方式极大提高了CPU的吞吐能力

并发编程有三个重要特性

  1. 原子性
    所谓原子性是指在一次的操作或者多次的操作中,要么所有的操作全部都得到了执行并且不会受到任何因素的干扰而中断,要么所有的操作都不执行。i++不能保证原子性,volatile关键字不保证数据的原子性,synchronized关键字保证
    多个原子性操作合在一起就不是原子性操作了
    简单的读取和赋值操作是原子性的,将一个变量赋值给另外一个变量的操作不是原子性的
    由于synchronized是一种排他机制,因此被他修饰的同步代码是无法被中途打断的,因此其能够保证代码的原子性。
  2. 可见性
    可见性是指当一个线程对共享变量进行了修改,那么另外的线程可以立即看到修改后的最新值
    synchronized和Lock保证可见性,他们会在(monitor exit)锁释放之前,会将对变量(共享资源)的修改刷新到主内存中
    volatile具有保证可见性的语义
  3. 有序性
    有序性是指程序代码在执行过程中的先后顺序,由于Java在编译器以及运行期的优化,导致了代码的执行顺序未必就是开发者编写代码时的顺序
    单利模式中的double-check的写法就是利用了volatile的顺序性

volatile保证了不同线程对共享变量操作时的可见性,也就是说当一个线程修改了volatile修饰的变量,另外一个线程会立即看到最新的值

volatile禁止JVM和处理器对使用volatile修饰的关键字进行指令进行重排序

i++的操作其实是由三步组成:

  1. 从主内存中获取i的值,然后缓存到线程的工作内存中
  2. 在线程工作内存中为i进行加1的操作
  3. 将i的最新值写入主内存中

volatile修饰的变量可以为null,synchronized关键字同步语句块的monitor对象不能为null

volatile不会使线程进入阻塞,synchronized关键字会使线程进入阻塞状态

上一篇 下一篇

猜你喜欢

热点阅读