Java内存模型之主内存与工作内存
每秒事务处理数量(TPS)是衡量一个服务性能高低好坏的重要指标之一。它代表着一秒内服务端平均能响应的请求综述,而且TPS值与程序的并发能力又有密切的关系。
为了解决计算机存储设备与处理器运算速度的差距,除了增加缓存外,还有一种优化方法,就是处理器可能会对输入的代码进行乱序执行,处理器在计算后会把乱序的结果进行重组,保证该结果与顺序执行时的一致,但是并不保证程序中各个语句计算的先后顺序与输入代码中的顺序一致。因此,出现一个计算任务依赖另一个计算任务的中间结果,那么其顺序性并不能靠代码的先后顺序来保证。
内存模型
可以理解为在特定的操作协议下,对特定的内存或高速缓存进行读写访问的过程抽象。
主内存与工作内存
Java内存模型的主要目的是定义程序中各种变量的访问规则,即关注虚拟机中把变量值存储到内存和从内存中取出变量值这样的底层细节。此处的变量包括了实例字段、静态字段和构成数组对象的元素,但是不包括局部变量与方法参数。因为后两个是线程私有的,并不会被共享,也不存在竞争。
Java内存模型没有限制执行引擎使用处理器的特定寄存器或缓存来和主内存进行交互,也没有限制即时编译器是否需要进行调整代码的执行顺序这类优化措施。
Java内存模型规定了所有的变量都存储在主内存中。每条线程还有自己的工作内存,线程的工作内存中保存了被该线程使用的变量的主内存副本,线程对变量的所有操作(读取,赋值等)都必须在工作内存中进行,而不能直接读写主内存的内容。不同线程也无法直接访问对方工作内存中的变量,线程间的变量值的传递均需要通过主内存来完成。
内存见的交互操作
如何将一个变量从主内存拷贝到工作内存以及如何从工作内存同同步回主内存,Java内存模型定义了8中操作来完成。虚拟机实现时必须保证这些操作是原子的、不可再分的。
lock(锁定):作用于主内存的变量。把一个变量标识为一条线程独占的。
unlock(解锁):作用于主内存。把一个处于锁定的变量释放,释放后可以被其他线程锁定。
read(读取):作用于主内存。把一个变量的值从主内存传输到线程的工作内存,用于后续load动作使用。
load(载入):作用于工作内存。把read操作从主内存中得到的变量值放入工作内存变量的副本中。
use(使用):作用于工作内存。把工作内存中的一个变量的值传递给执行引擎。当虚拟机遇到一个需要使用变量的值的字节码指令时,将会执行这个操作。
assign(赋值):作用于工作内存。把一个从执行引擎接收的值,赋给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时,会执行这个操作。
store(存储):作用于工作内存。把工作内存中一个变量的值传送到主内存中,方便后续write操作使用。
write(写入):主内存变量。把store操作从工作内存中得到的变量的值放入主内存变量。
如果要把一个变量从主内存拷贝到工作内存,那就要顺序执行read和load操作,如果要把变量从工作内存同步回主内存,就要顺序执行store和write操作。Java内存模型只要求上述两个操作必须顺序执行,但不要求是连续执行的。也就是说执行中间可以插入其他的执行。
参考
《深入理解Java虚拟机》