并发处理就是压榨处理器运算能力,使处理器内部运算单元被充分利用。

1. 硬件的效率与一致性

由于计算机的处理器与存储设备的运算速度存在几个数量级的差距,所以在内存与处理器之间加入运算速度接近处理器的高速缓存作为缓冲。运算时将运算数据从主内存复制到缓存,当运算结束后再从缓存同步回内存,从而减少等待时间。 image.png-24.4kB

高速缓存解决了处理器与内存的速度矛盾,同时也引入新问题:缓存一致性(Cache Coherence)。即如何保证各处理器的高速缓存内数据与主内存数据一致性呢?这就需要各处理器访问数据时准守一些协议。“内存模型”可以理解为在特定操作协议下,特定的内存或高速缓存进行读写访问的过程抽象。 处理器还会对代码进行乱序执行(Out-of-order Execution)优化,再将乱序执行的结果进行重组,保证该结果与顺序执行的结果一致,而不依赖于代码的先后顺序。从而提高处理器运算单元利用率。

2. Java内存模型

Java虚拟机规范中定义Java内存模型(JMM),从而达到Java程序于各平台访问内存一致。

2.1 主内存与工作内存

Java内存模型规定所有变量都存储于主内存中,每条线程拥有自己工作内存。工作内存保存了该线程所用的变量的主内存副本拷贝,线程对变量的所有操作只在工作内存中进行,线程间变量的值传递需通过主内存完成。

image.png-24.1kB

注意: 此处变量包括实例变量、静态字段和构成数组对象的元素,不包括局部变量和方法参数,因后者是线程私有的,不被共享,也就不存在竞争。

2.2 内存间交互操作

Java内存模型定义8种操作来完成主内存与工作内存之间的数据交互。 下面每种操作都是原子的,不可再分的,但对于double和long类型变量在某些平台允许有例外。

  • lock(锁定)
  • unlock
  • read
  • load
  • use
  • assign
  • store
  • write Java内存模型要求以上操作必须按顺序执行,但不保证是连续执行。也就是read与load之间是可插入其他指令的,如访问主内存a、b变量,可能出现的顺序是read a、read b、load b、load a。

Java内存模型还规定执行8种操作时必须满足如下规则:

这种定义相当严谨,但又十分烦琐,实践起来很麻烦,稍后介绍等效判定原则-先行发生原则,用来判定一个访问在并发环境下是否安全。