Java 自旋锁与读写锁
一、自旋锁的核心概念
自旋锁(Spin Lock)是一种非阻塞锁,它的核心思想是:当线程获取锁失败时,不会立刻进入阻塞(休眠)状态,而是在一个循环中不断尝试获取锁('自旋'),直到成功获取锁或者达到自旋上限。
二、对比传统阻塞锁(如 synchronized)
- 阻塞锁:获取锁失败 → 线程进入等待队列 → 内核态切换 → 等待被唤醒 → 再次竞争锁(上下文切换成本高)
- 自旋锁:获取锁失败 → 循环重试(用户态) → 成功获取锁(无上下文切换)
自旋锁适合锁持有时间极短的场景,因为短时间的自旋消耗的 CPU 资源,远小于线程上下文切换的开销;但如果锁持有时间长,自旋会浪费大量 CPU 资源(空转)。
三、Java 中自旋锁的实现原理
Java 中实现自旋锁的核心是CAS(Compare And Swap,比较并交换) 操作,这是一种原子操作,保证多线程下的线程安全。
CAS 有三个核心参数:
V:要修改的变量(锁的状态标识)A:预期值(期望的锁状态,比如未被占用)B:新值(修改后的锁状态,比如被当前线程占用)
只有当 V == A 时,才会将 V 更新为 B,否则不做操作,返回 false。
import java.util.concurrent.atomic.AtomicReference;
/**
* 简单的自旋锁实现
* 核心:利用 AtomicReference 的 CAS 操作保证锁的原子性竞争
*/
public class SimpleSpinLock {
// 用 AtomicReference 存储持有锁的线程,初始为 null(无锁状态)
private final AtomicReference<Thread> lockOwner = new AtomicReference<>();
// 获取锁(自旋逻辑)
public void lock() {
Thread currentThread = Thread.currentThread();
// 自旋:CAS 尝试将 lockOwner 从 null 改为当前线程,失败则循环重试
while (!lockOwner.compareAndSet(null, currentThread)) {
// 空循环(自旋),也可以加入自旋次数限制、yield() 等优化
// Thread.yield(); // 让出 CPU,减少空转消耗
}
System.out.println(currentThread.getName() + );
}
{
Thread.currentThread();
(lockOwner.get() == currentThread) {
lockOwner.compareAndSet(currentThread, );
System.out.println(currentThread.getName() + );
} {
();
}
}
{
();
( ; i < ; i++) {
(() -> {
{
spinLock.lock();
Thread.sleep();
} (InterruptedException e) {
Thread.currentThread().interrupt();
} {
spinLock.unlock();
}
}, + i).start();
}
}
}

