1 volatile
在Java中,volatile关键字用于解决多线程环境下的可见性和指令重排序问题,是轻量级的同步机制。
1.1 多线程间可见性
JMM:Java内存模型
volatile修饰变量,保证:
2 写操作:立即刷新到主内存,并使其他线程的缓存行失效
读操作:直接从主内存读取最新值
底层实现:通过lock指令和缓存一致性协议(如MESI)实现
1.2 禁止指令重排序
Java的编译器在不影响程序结果的情况下,会对指令进行重排序,增强程序的执行效率。volatile禁止了指令重排序,在两个操作数之间添加一个内存屏障(可以理解我一个指令)。
经典案例:volatile + DCL实现单例模式
/*** DCL + volatile 实现单例模式*/
public class Code01_VolatielSingleton {// volatile声明 禁止指令重排序private static volatile Code01_VolatielSingleton instance;private Code01_VolatielSingleton() {}public static Code01_VolatielSingleton getInstance() {if (instance == null) {synchronized (Code01_VolatielSingleton.class) {if (instance == null) {instance = new Code01_VolatielSingleton();}}}return instance;}}
2 Atomic系列类(原子类)
Java在java.util.concurrent.atomic包中,提供了原子性操作的一系列类(AtomicInteger, AtomicLong, AtomicReference<V>等),保证多线程下的安全。其核心目标是通过无锁(Lock-Free)的原子操作替代传统的锁机制,解决多线程环境下的共享变量操作问题,提升并发性能。
(1)核心机制:CAS与无锁同步
原子类通过CAS(Compare-And-Swap)指令实现无锁同步,其本质是依赖底层硬件支持的原子操作。CAS即比较当前值与预期值,若一致则更新为新值;否则重试或失败。
public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
(2)原子类操作场景问题
① 复合操作的非原子性
原子类仅保证单个操作的原子性,多个原子操作的组合仍需同步
② ABA问题
线程A读取值为A,线程B修改为B后再次改回A,导致A误判值未变
解决:使用AtomicStampedReference,添加版本号控制
③ 频繁CAS操作性能瓶颈
CAS执行次数过多,CPU会一直调度这个线程,造成性能损耗
解决1-synchronized实现方式:CAS自旋一定次数后还不成功就挂起线程
解决2-LongAdder实现方式:当CAS失败后,将操作的值存储起来,后续一起相加(分段累加)
(3)Unsafe类
Unsafe 类是 sun.misc 包下的内部工具类,提供底层内存操作、线程调度、CAS(Compare-And-Swap)原子操作等能力。
单例模式:构造函数私有化,通过静态方法 getUnsafe() 获取实例。
提供的核心功能:
① 内存操作
// 分配堆外内存
public native long allocateMemory(long var1);// 释放内存
public native void freeMemory(long var1);// 调整内存大小
public native long reallocateMemory(long var1, long var3);
② 字段的定位和修改
// 获取对象字段的内存偏移量
public native long objectFieldOffset(Field var1);/**AtomicInteger中使用
*/
static {try {valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));} catch (Exception ex) { throw new Error(ex); }
}
③ CAS操作(乐观锁):是 AtomicInteger 等原子类的底层实现
public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);
④ 线程挂起和恢复
// 恢复指定线程
public native void unpark(Object var1);
// 挂起当前线程
public native void park(boolean var1, long var2);
⑤ 内存屏障:插入内存屏障,禁止指令重排序
public native void loadFence();public native void storeFence();public native void fullFence();
3 AQS:AbstractQueuedSynchronizer
AQS 是 Java 并发包中构建锁和同步器的基础框架,通过 FIFO 等待队列、同步状态管理和模板方法模式实现高效线程同步,支持独占(如 ReentrantLock)和共享(如 Semaphore)两种模式。
核心结构
(1)state:volatile修饰的int类型变量,多个线程会通过CAS的方式修改state
(2)双向链表:基于内部类Node维护,包含prev、next、thread等属性
Node节点
static final class Node {volatile int waitStatus; // 节点状态(如CANCELLED、SIGNAL)volatile Node prev; // 前驱节点volatile Node next; // 后继节点volatile Thread thread; // 关联的线程
}
(3)模板方法模式,子类实现,需重写这些模板方法定义同步逻辑
protected boolean tryAcquire(int arg); // 独占模式获取资源
protected boolean tryRelease(int arg); // 独占模式释放资源
protected int tryAcquireShared(int arg); // 共享模式获取资源
protected boolean tryReleaseShared(int arg);// 共享模式释放资源
常用子类实现
① ReentrantLock:基于独占模式实现可重入锁
② ReentrantReadWriteLock:既有独占模式,又有共享模式实现的读写锁
③ CountDownLatch:通过共享模式实现线程等待
④ Semaphore:基于共享模式控制并发访问数