在多线程并发编程中synchronized和volatile都扮演着重要的角色,volatile是轻量级的synchronized,他在多处理器开发中保证了共享变量的可见性。可见性的意思是当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值。如果volatile变量修饰符使用恰当的话,它比synchronized是使用和执行成本更低,因为它不会引起线程上下文的切换和调度。
1.volaile的定义与实现原理
Java语言规范第3版中对volatile的定义如下:
- Java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致地更新,线程应该确保通过排它锁单独获取这个变量。
- Java语言提供了volatile,在某些情况下比锁要更加方便。如果一个字段被声明成volatile,Java线程内存模型确保所有线程看到这个变量的值是一致的。
在了解volatile实现原理之前,我们先来看下与其实现原理相关的CPU术语和说明:
术语 | 英文单词 | 术语描述 |
---|---|---|
内存屏障 | memory barriers | 是一组处理器指令,用于实现对内存操作的顺序限制 |
缓冲行 | cache line | CPU高速缓存中可以分配的最小存储单位。处理器填写缓存行时会加载整个缓存行,现在CPU需要执行几百次CPU指令 |
原子操作 | atomic operations | 不可中断的一个或一系列操作 |
缓存行填充 | cache line fill | 当处理器识别到内存中读取操作是可缓存的,处理器读取整个高速缓存行到适当的缓存(L1,L2,L3或所有) |
缓存命中 | cache hit | 如果进行高速缓存行填充操作的内存位置仍然是下次处理器访问的地址时,处理器从缓存中读取操作数,而不是内存读取 |
写命中 | write hit | 当处理器将操作数写回到一个内存缓存的区域时,它会首先检查这个缓存的内存地址是否在缓存行中,如果存在一个有效的缓存行,则处理器将这个操作数写回到缓存,而不是写回到内存,这个操作被称为写命中 |
写缺失 | write misses the cache | 一个有效的缓存行被写入到不存在的内存区域 |
首先看下volatile如何保证可见性的。通过工具获取JIT编译