Java多线程并发(6)volatile(1)

35 阅读3分钟

在对volatile关键字进行详细解析之前,我们需要对java内存模型有一个清晰的认识。

JMM

JMM是java内存模型,他不同于JVM的运行时内存区,它是抽象的概念,并不是真实物理存在的,相当于一组规则

  • JMM规定所有的变量存储在主内存中,是线程共享区

那么每个线程想要操作变量首先需要将它复制到自己的工作内存中,之后再复制到主内存中

主内存:存储Java所有实例对象(不管是局部还是成员)由于是共享数据区域,多条线程对同一个变量进行非原子性操作时可能会发现线程安全问题。

工作内存:线程私有内存。

JMM的关键就是围绕多线程的原子性、可见性、有序性。

它能够屏蔽各个硬件平台和操作系统访问内存的性能差异,从而达到Java在各种平台下内存访问一致的效果。

就像高速缓存和内存之间缓存一致性协议的存在一样。

三大特性

可见性

共享变量的值的修改,在所有线程立马可见。

JMM规定了所有的变量存储在主内存中,每个线程所使用的是共享变量的副本,不会直接访问主内存的变量。

原子性

线程的操作不能被打断,当多个线程对共享变量进行修改的时候,其他线程对正在执行的线程不能造成影响。

有序性

JVM会对指令进行重排序,使其符合CPU执行特性,但是在多线程的状态下,可能出现“脏读”。

所以有时候会关闭重排序。

不同线程之间不能够相互访问线程工作内存的变量。

happens-before

  • 如果一个操作发生在(happens-before)另一个操作之前,那么第一个操作的执行结果将对第二个操作可见
  • 两个操作之间存在happens-before关系,如果重排序后按照这种关系的执行的结果一致,那么重排序并不非法

八大规则

  • 次序规则:一个线程内,按照代码顺序进行执行。
  • 锁定规则:一个unLock操作可以先发生于对锁的lock,这个”先于“是时间上的先后
  • volatile变量规则:对volatile边浪的写操作先发生于读操作,前面的写对后面的度可见
  • 传递规则:如果A先于B,B先于C,A肯定先于C
  • 线程启动规则:线程的start()优先每一个动作
  • 线程中断规则:被中断线程的代码检测中断之前,应先使用interrupt方法
  • 线程终止规则:线程所有操作先行发生于线程的终止检测
  • 对象终结规则:一个对象先被初始化,然后才能回收