天天看点

java并发机制_Java并发机制的底层实现原理.PDF

Java并发机制的底层实现原理

Chapter 2 第2 章

Java 并发机制的底层实现原理

Java 代码在编译后会变成 Java 字节码,字节码被类加载器加载到 JVM 里,JVM 执行字

节码,最终需要转化为汇编指令在 CPU 上执行 ,Java 中所使用的并发机制依赖于 JVM 的实

现和 CPU 的指令。本章我们将深入底层一起探索下 Java 并发机制的底层实现原理。

2.1 volatile 的应用

在多线程并发编程中 synchronized 和 volatile 都扮演着重要的角色,volatile 是轻量级的

synchronized ,它在多处理器开发中保证了共享变量的“可见性”。可见性的意思是当一个线

程修改一个共享变量时,另外一个线程能读到这个修改的值。如果 volatile 变量修饰符使用

恰当的话,它比 synchronized 的使用和执行成本更低,因为它不会引起线程上下文的切换和

调度。本文将深入分析在硬件层面上 Intel 处理器是如何实现 volatile 的,通过深入分析帮助

我们正确地使用 volatile 变量。

我们先从了解 volatile 的定义开始。

1. volatile 的定义与实现原理

Java 语言规范第 3 版中对 volatile 的定义如下 :Java 编程语言允许线程访问共享变量,

为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。

Java 语言提供了 volatile ,在某些情况下比锁要更加方便。如果一个字段被声明成 volatile ,

Java 线程内存模型确保所有线程看到这个变量的值是一致的。

在了解 volatile 实现原理之前 ,我们先来看下与其实现原理相关的 CPU 术语与说明。

第2 章 Java 并发机制的底层实现原理   9

表 2-1 是 CPU 术语的定义。

表2-1 CPU 的术语定义

术  语 英文单词 术语描述

内存屏障 memory barriers 是一组处理器指令,用于实现对内存操作的顺序限制

缓存中可以分配的最小存储单位。处理器填写缓存线时会加载整个

缓冲行 cache line

缓存线,需要使用多个主内存读周期

原子操作 atomic operations 不可中断的一个或一系列操作

当处理器识别到从内存中读取操作数是可缓存的,处理器读取整个

缓存行填充 cache line f ill

缓存行到适当的缓存(L1 ,L2 ,L3 的或所有)

如果进行高速缓存行填充操作的内存位置仍然是下次处理器访问的

缓存命中 cache hit

地址时,处理器从缓存中读取操作数,而不是从内存读取

当处理器将操作数写回到一个内存缓存的区域时,它首先会检查这

个缓存的内存地址是否在缓存行中,如果存在一个有效的缓存行,则

写命中 write hit

处理器将这个操作数写回到缓存,而不是写回到内存,这个操作被称

为写命中

写缺失 write misses the cache 一个有效的缓存行被写入到不存在的内存区域

volatile 是如何来保证可见性的呢?让我们在 X86 处理器下通过工具获取 JIT 编译器生

成的汇编指令来查看对 volatile 进行写操作时,CPU 会做什么事情。

Java 代码如下。

instance = new Singleton(); //