一、Synchronized
(一)特点
1、synchronized是Java中实现线程同步的关键字,它提供了互斥性和可见性保证
2、JVM层面锁(内置锁),基于Monitor(对象监视器)实现
3、可重入 (Reentrant Lock),同一线程可多次获取同一把锁,避免死锁
4、悲观锁,线程获取锁前会阻塞其他线程,认为并发冲突频繁,先加锁再操作
5、非公平锁,允许线程"插队"获取锁,提高吞吐量但可能导致饥饿
6、阻塞锁,线程获取锁失败时,进入阻塞状态,编译时自动生成 monitorenter和monitorexit 字节码指令
7、对象级锁,锁定对象实例或代码块,同步非静态方法或 synchronized(this),多个线程竞争同一个对象的锁
方法同步:public synchronized void method()
代码块同步:synchronized(obj) {...}
8、类级锁,锁定类的Class对象或静态同步方法或synchronized(Class.class),所有实例共享同一把锁
(二)结构

可视化工具
JOL (Java Object Layout):通过 jol-core 库打印对象内存布局,直接观察Mark Word
java
Object obj = new Object();
System.out.println(ClassLayout.parseInstance(obj).toPrintable());
输出示例(64位无锁状态)
java
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168317)
12 4 (loss due to the next object alignment)
前8字节为Mark Word(0x0000000000000001,锁标志为01,表示无锁)
Mark Word锁状态转换

(一)JVM 内部优化(synchronized锁升级过程)
无锁 → 偏向锁 → 轻量级锁 → 重量级锁
-
无锁状态:初始状态
-
偏向锁:无竞争时偏向第一个获取锁的线程
-
轻量级锁:多线程竞争不激烈时,通过CAS获取
-
重量级锁:竞争激烈时升级为操作系统互斥锁(mutex)

重量级锁依赖于 Monitor 对象(也称为管程或监视器锁),每个 Java 对象都可以关联一个 Monitor 对象。
Monitor 结构
java
ObjectMonitor {
_header = NULL; // 对象头
_count = 0; // 重入次数
_waiters = 0; // 等待线程数
_recursions = 0; // 锁重入次数
_object = NULL; // 关联的对象
_owner = NULL; // 持有锁的线程
_WaitSet = NULL; // 处于 wait 状态的线程队列
_cxq = NULL; // 竞争队列
_EntryList = NULL; // 等待锁的线程队列
}
Monitor工作流程图

二、ReentrantLock
(一)特点
1、Java并发包(java.util.concurrent.locks)中的一个可重入互斥锁,通过 Lock接口和实现类提供更灵活的锁操作(如可中断、超时、公平性等)。
2、基于AQS (AbstractQueuedSynchronizer),Java并发包中锁的核心实现框架
3、JUC层面(显式锁Explicit Lock),支持公平/非公平模式
-
ReentrantLock(true):公平锁,按照线程请求顺序获取锁,遵循先到先得原则(FIFO)
-
ReentrantLock(false):默认非公平锁,允许线程"插队"获取锁,提高吞吐量但可能导致饥饿
4、可重入 (Reentrant Lock),同一线程可多次获取同一把锁,避免死锁
5、条件锁 (Condition Lock),基于条件变量实现线程等待/通知机制,条件变量支持newCondition()
6、悲观锁,认为并发冲突频繁,线程获取锁前会阻塞其他线程,先加锁再操作
7、对象级锁锁定对象实例或代码块,多个线程竞争同一个对象的锁。
8、阻塞锁,线程获取锁失败时,进入阻塞状态,可中断的获取锁lockInterruptibly(),超时获取锁tryLock(long timeout, TimeUnit unit)
(二)类继承关系
java
java.util.concurrent.locks.ReentrantLock
├── FairSync (公平锁)
└── NonfairSync (非公平锁)
└── Sync (抽象基类)
└── AbstractQueuedSynchronizer (AQS)
1、非公平锁实现
nonfairTryAcquire (非公平锁尝试获取)
java
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) { // 锁未被持有
if (compareAndSetState(0, acquires)) { // CAS获取
setExclusiveOwnerThread(current); // 设置持有线程
return true;
}
} else if (current == getExclusiveOwnerThread()) { // 可重入
int nextc = c + acquires;
if (nextc < 0) throw new Error("Maximum lock count exceeded");
setState(nextc); // 增加重入次数
return true;
}
return false;
}
tryRelease (尝试释放锁)
java
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// 计数器归零
if (c == 0) {
free = true;
// 清除持有线程
setExclusiveOwnerThread(null);
}
// 更新状态
setState(c);
return free;
}
2、公平锁实现
java
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() && // 检查队列中是否有等待线程
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
} else if (current == getExclusiveOwnerThread()) {
// 重入
int nextc = c + acquires;
if (nextc < 0) throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
关键区别:
非公平锁:新线程可以直接插队尝试获取锁
公平锁:必须检查队列中是否有等待线程,遵循FIFO原则
公平与非公平锁对比
特性 | 公平锁 | 非公平锁 |
---|---|---|
锁获取顺序 | 严格按照请求顺序 | 可能插队 |
吞吐量 | 较低 | 较高 |
避免线程饥饿 | 是 | 否 |
实现方式 | 请求时检查队列 | 先尝试获取,失败再入队 |
(三)AQS核心机制
1、同步状态管理
state 字段:32位整型,表示同步状态
独占模式:0表示未获取,1表示已获取,>1表示重入
共享模式:表示可被多个线程获取的许可数量

2、FIFO等待队列
CLH 队列变种:双向链表实现的FIFO队列
节点状态:
CANCELLED=1:线程已取消等待
SIGNAL=-1:后继节点需要被唤醒
CONDITION=-2:节点在条件队列中
PROPAGATE=-3:共享模式下传播释放信号

3、独占模式流程
java
public final void acquire(int arg) {
if (!tryAcquire(arg) && // 尝试获取
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) // 获取失败则入队
selfInterrupt();
}
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor(); // 获取前驱
if (p == head && tryAcquire(arg)) { // 如果是head的后继
setHead(node); // 设置自己为head
p.next = null; // 帮助GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) && // 检查是否需要阻塞
parkAndCheckInterrupt()) // 阻塞线程
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}


4、共享模式流程
java
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0) // 尝试获取共享许可
doAcquireShared(arg); // 获取失败则入队
}
private void doAcquireShared(int arg) {
final Node node = addWaiter(Node.SHARED); // 加入共享节点
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg); // 尝试获取
if (r >= 0) { // 成功
setHeadAndPropagate(node, r); // 设置head并传播信号
p.next = null;
if (interrupted)
selfInterrupt();
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
共享模式与独占模式对比

关键方法说明
tryAcquire(int):独占模式获取同步状态(需子类实现)
tryRelease(int):独占模式释放同步状态(需子类实现)
tryAcquireShared(int):共享模式获取同步状态(需子类实现)
tryReleaseShared(int):共享模式释放同步状态(需子类实现)
isHeldExclusively():判断当前线程是否独占同步状态(需子类实现)

(四)AQS在JUC中应用

ReentrantLock与synchronized对比
特性 | ReentrantLock | synchronized |
---|---|---|
实现机制 | AQS+CAS | JVM内置monitor |
锁获取方式 | 显式lock()/unlock() | 隐式(代码块/方法) |
公平性 | 可配置公平/非公平 | 非公平 |
可中断 | 支持(lockInterruptibly) | 不支持 |
超时机制 | 支持(tryLock) | 不支持 |
条件变量 | 支持(多个Condition) | 单一wait/notify |
性能 | 高竞争下表现更好 | 优化后性能相当 |
三、ReentrantReadWriteLock
JUC层面,显式锁 (Explicit Lock),读写锁 (Read-Write Lock),分读锁和写锁,允许多线程并发读,但写操作独占,java.util.concurrent.locks包下的锁,通过Lock接口和实现类提供更灵活的锁操作(如可中断、超时、公平性等)。
(一)特点
1、读写分离:读锁(共享锁)和写锁(独占锁)分离
2、重入性:支持重入,同一个线程可以多次获取同一把锁
3、公平性选择:支持公平和非公平两种模式
4、锁降级:允许从写锁降级为读锁
(二)核心组件
Sync:抽象同步器,继承自AQS(AbstractQueuedSynchronizer)
FairSync:公平锁实现
NonfairSync:非公平锁实现
Holder:持有锁的线程信息
State:同步状态,高16位表示读锁状态,低16位表示写锁状态
(三)同步状态设计
ReentrantReadWriteLock 使用一个 32 位的 int 类型的 state 来表示锁状态

(四)代码查看
1、读锁获取 (doAcquireShared)
java
protected final int tryAcquireShared(int unused) {
Thread current = Thread.currentThread();
int c = getState();
// 检查写锁是否被其他线程持有
if (exclusiveCount(c) != 0 &&
getExclusiveOwnerThread() != current)
return -1;
int r = sharedCount(c);
if (!readerShouldBlock() &&
r < MAX_COUNT &&
compareAndSetState(c, c + SHARED_UNIT)) {
// 成功获取读锁
if (r == 0) {
firstReader = current;
firstReaderHoldCount = 1;
} else if (firstReader == current) {
firstReaderHoldCount++;
} else {
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current))
cachedHoldCounter = rh = readHolds.get();
else if (rh.count == 0)
readHolds.set(rh);
rh.count++;
}
return 1;
}
// 获取失败,进入等待队列
return fullTryAcquireShared(current);
}
2、写锁获取 (tryAcquire)
java
protected final boolean tryAcquire(int acquires) {
Thread current = Thread.currentThread();
int c = getState();
int w = exclusiveCount(c);
if (c != 0) {
// 存在读锁或写锁被其他线程持有
if (w == 0 || current != getExclusiveOwnerThread())
return false;
if (w + exclusiveCount(acquires) > MAX_COUNT)
throw new Error("Maximum lock count exceeded");
// 重入
setState(c + acquires);
return true;
}
// 检查是否应该阻塞(公平性)
if (writerShouldBlock() ||
!compareAndSetState(c, c + acquires))
return false;
setExclusiveOwnerThread(current);
return true;
}
(五)流程图


四、StampedLock
StampedLock (Java 8+)改进的读写锁,它提供了比ReentrantReadWriteLock更灵活的锁操作,特别适合读多写少的场景。读锁不阻塞写锁(通过版本戳机制),支持锁升级和降级,性能优于ReentrantReadWriteLock在高并发读场景
(一)支持三种模式
1、写锁(exclusive lock)独占锁
获取:long stamp = lock.writeLock()
释放:lock.unlockWrite(stamp)
特点:独占锁,与其他所有模式互斥
2、悲观读锁(pessimistic read lock)类似ReadWriteLock的读锁,共享锁
获取:long stamp = lock.readLock()
释放:lock.unlockRead(stamp)
特点:共享锁,与写锁互斥,与其他读锁不互斥
3、乐观读(optimistic read)不阻塞写操作,需后续验证
获取:long stamp = lock.tryOptimisticRead()
验证:lock.validate(stamp)
特点:不阻塞,没有真正的锁获取,只是获取一个戳记用于后续验证
(二)数据结构
StampedLock内部使用一个long类型的state变量来存储所有状态信息,通过位运算来区分不同状态

状态转换图

(三)代码查看
1、乐观读
乐观读不获取实际锁,只是读取当前状态作为"戳记"(stamp)
java
public long tryOptimisticRead() {
long stamp = state;
// 检查是否有写锁
if ((stamp & WBIT) != 0L) {
return 0L; // 有写锁则返回0表示失败
}
return stamp; // 返回当前状态作为戳记
}
2、悲观读锁
悲观读锁会阻塞写操作
java
public long readLock() {
long s, next; // 忽略重试逻辑
for (;;) {
s = state;
// 检查是否有写锁或写线程在等待
if (((s & WBIT) != 0L) || ((s & (WBIT - 1)) != 0L)) {
// 阻塞等待
} else if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT)) {
return next;
}
}
}
3、写锁
写锁是独占锁
java
public long writeLock() {
long s, next; // 忽略重试逻辑
for (;;) {
s = state;
// 检查是否有任何读锁或写锁
if ((s & WBIT) != 0L || (s != 0L)) {
// 阻塞等待
} else if (U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) {
return next;
}
}
}
五、Atomic
Atomic(原子性)操作是指不可中断的一个或一系列操作,这些操作要么全部执行成功,要么全部不执行,不会出现执行到中间状态的情况
(一)CPU支持
Atomic操作的实现主要依赖于CPU提供的原子指令
1、比较并交换 (CAS - Compare And Swap)
指令示例:x86的CMPXCHG
操作:比较内存值与期望值,如果相同则替换为新值
2、原子加载-存储
指令示例:x86的MOV带LOCK 前缀
操作:保证加载或存储操作的原子性
3、其他原子指令
递增/递减(INC/DEC 带 LOCK)
交换(XCHG)
(二)处理器
不同处理器架构实现原子操作的方式不同
架构 | 实现方式 |
---|---|
x86 | 使用LOCK前缀指令锁定总线或缓存行 |
ARM | 使用LL/SC指令对 |
RISC-V | 使用AMO(Atomic Memory Operation)指令 |
(三)CAS(Compare And Swap)原理

1、Java中的CAS
java
public final class Unsafe {
public final native boolean compareAndSwapObject(
Object o, long offset, Object expected, Object x);
public final native boolean compareAndSwapInt(
Object o, long offset, int expected, int x);
public final native boolean compareAndSwapLong(
Object o, long offset, long expected, long x);
}
2、CAS典型应用AtomicInteger实现
java
public class AtomicInteger {
private volatile int value;
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
}
3、ABA问题
初始: A → B → A (内存值变化过程)
Thread1 看到 A,准备更新为C
Thread2 快速将 A→B→A
Thread1 认为值没变(还是 A),执行CAS成功
但实际中间经历了变化
解决方案
版本号/时间戳(如 Java 的 AtomicStampedReference)
危险指针(如 C++ 的 hazard_pointer)
4、不同语言Atomic实现
语言 | 底层机制 | 典型类/函数 |
---|---|---|
Java | Unsafe + CAS | AtomicInteger, AtomicReference |
C++11 | std::atomic | compare_exchange_strong |
Go | runtime + CAS | sync/atomic包 |
Rust | Atomic*类型 | std::sync::atomic |
(四)LL/SC (Load-Linked/Store-Conditional) 加载链接/条件存储
LL/SC(Load-Linked/Store-Conditional)是现代 CPU(如 ARM、PowerPC、RISC-V)提供的一种原子操作机制,用于实现无锁同步(lock-free programming)。它与 CAS(Compare-And-Swap) 类似,采用"乐观读取-条件写入"的方式,避免了CAS的ABA 问题。
1、LL/SC指令组成
LL(Load-Linked)
读取内存中的值,并 标记该内存位置(类似于"监视"该地址)。
如果其他线程修改了该地址,标记会失效。
SC(Store-Conditional)
尝试将新值写入 LL 标记的内存位置。
仅当该地址未被其他线程修改过 时,写入成功(返回 success),否则失败(返回 fail)。
如果失败,通常需要重新执行 LL 和 SC 循环。

2、不同架构实现差异
架构 | LL指令 | SC指令 | 保留粒度 |
---|---|---|---|
ARM | LDREX | STREX | 通常缓存行大小 |
MIPS | LL | SC | 实现定义 |
PowerPC | lwarx | stwcx. | 缓存行 |
RISC-V | LR.W/D | SC.W/D | 实现定义 |
3、LL/SC vs CAS
特性 | LL/SC | CAS |
---|---|---|
关键指令 | LL/SC 或 LDXR/STXR | CMPXCHG |
适用CPU | ARM、RISC-V、PowerPC | x86、AMD64 |
灵活性 | 更高(可在两条指令间插入其他操作) | 较低 |
伪失败 | 更常见(因监控粒度较大) | 较少 |
工作方式 | 乐观读取+条件写入 | 比较并交换 |
ABA问题 | 天然避免(SC会检测修改) | 可能受ABA问题影响 |
性能 | 高并发时可能更好(减少竞争) | 高竞争时可能自旋较多 |
(五)内存屏障(Memory Barriers)保证指令执行顺序
内存屏障(Memory Barrier,也称内存栅栏)是一种CPU指令,用于控制指令执行顺序和内存可见性,解决多核处理器中的内存乱序问题。
1、内存屏障核心
1)防止指令重排序
编译器优化:编译器可能调整指令顺序以提高性能(如将写操作移到循环外)。
CPU 乱序执行:现代 CPU 采用乱序执行(Out-of-Order Execution)和分支预测,导致指令实际执行顺序与代码顺序不一致。
内存屏障:强制 CPU 和编译器 按顺序执行屏障前后的指令,避免乱序。
2)保证内存可见性
缓存一致性协议(MESI):多核 CPU 通过缓存一致性协议保证缓存同步,但可能存在延迟。
内存屏障:强制刷新 CPU 缓存,确保屏障前的写操作对其他线程可见,屏障后的读操作能读取最新值。
MESI状态
状态 | 含义 |
---|---|
Modified(M) | 缓存行已被当前核心修改,且未写回主存,其他核心的缓存行必须为 Invalid |
Exclusive(E) | 缓存行未被修改,且仅当前核心持有,其他核心无此缓存行(可能主存未更新) |
Shared(S) | 缓存行未被修改,且多个核心共享此缓存行(内容与主存一致) |
Invalid(I) | 缓存行无效(未加载或已被其他核心修改) |
2、内存屏障分类
内存屏障分为 4 种基本类型,根据作用方向(读/写)和屏障强度(全屏障/单向屏障)组合而成
类型 | 作用 | 典型指令 |
---|---|---|
LoadLoad | 保证前面的Load先于后面的Load | LOAD_A; Barrier; LOAD_B |
StoreStore | 保证前面的Store先于后面的Store | STORE_A; Barrier; STORE_B |
LoadStore | 保证前面的Load先于后面的Store | LOAD_A; Barrier; STORE_B |
StoreLoad | 保证前面的Store先于后面的Load | STORE_A; Barrier; LOAD_B |
Load = 读,Store = 写
屏障名称格式:[屏障前操作][屏障后操作]
如 StoreLoad = 确保写操作在读操作前完成
强度分类
完全屏障(Full Barrier) > 获取屏障(Acquire) > 释放屏障(Release) > 编译屏障
3、内存屏障与原子操作
原子操作通常隐含内存屏障:
原子读:包含获取语义(Acquire)
原子写:包含释放语义(Release)
RMW操作:包含完全屏障(Full Barrier)
4、内存屏障的作用
1)无内存屏障时的乱序问题
java
// 线程1
x = 1; // 写操作
flag = true; // 写操作
// 线程2
if (flag) { // 读操作
print(x); // 读操作
}
可能的重排序结果(导致线程2打印 x=0)
java
线程1: flag = true; x = 1; // 编译器/CPU 调整顺序
线程2: if (flag) { print(0); } // 读取到旧值
2)插入StoreLoad Barrier后的正确顺序
java
// 线程1
x = 1;
StoreLoad Barrier; // 确保 x=1 对其他线程可见后再设置 flag
flag = true;
// 线程2
if (flag) {
LoadLoad Barrier; // 确保读取 flag 后再读取 x
print(x);
}
执行顺序保证
线程1 的 x=1 必须在线程2 读取 flag 前完成。
线程2 读取 flag 后,必须读取最新的 x 值。
3)Java内存模型(JMM)
volatile 关键字:
编译器插入 StoreLoad Barrier(mfence 或 lock addl)。
确保写操作对其他线程立即可见。
synchronized 关键字:
进入同步块时插入 LoadLoad + StoreStore 屏障。
退出同步块时插入 StoreLoad 屏障。
5、内存屏障应用场景
1)无锁数据结构(Lock-Free)
java
// 原子引用更新(CAS + 内存屏障)
public class AtomicReference<T> {
private volatile T value;
public boolean compareAndSet(T expected, T newValue) {
// CAS 操作隐含 StoreLoad 屏障
return unsafe.compareAndSwapObject(this, valueOffset, expected, newValue);
}
}
2)双检锁单例模式(DCL)
java
public class Singleton {
private static volatile Singleton instance;
public static Singleton getInstance() {
if (instance == null) { // 第一次检查
synchronized (Singleton.class) {
if (instance == null) { // 第二次检查
instance = new Singleton(); // 写操作 + 内存屏障
}
}
}
return instance;
}
}
volatile 作用:
防止 instance = new Singleton() 被重排(对象未初始化完成就被发布)。
3)JVM 内部实现
Unsafe.putOrderedObject():
仅保证写操作顺序(StoreStore),不保证可见性(比 volatile 更轻量)。
Unsafe.fullFence():
插入全屏障(StoreLoad)
6、内存屏障总结
屏障类型 | 作用 | 典型场景 |
---|---|---|
LoadLoad | 防止读操作重排到读操作之前 | 无锁读、volatile 读 |
StoreStore | 防止写操作重排到写操作之后 | 无锁写、volatile 写 |
StoreLoad | 防止写操作重排到读操作之前 | CAS、双检锁、volatile 写读 |
全屏障 | 防止所有读写操作重排 | 同步块退出、JVM 内部同步 |
六、CountDownLatch / CyclicBarrier / Semaphore
虽非传统锁,但用于协调线程执行,属于广义同步工具
七、LockSupport
提供更底层的线程阻塞/唤醒支持如 park()/unpark()
八、选择建议
场景 | 建议 |
---|---|
低竞争、简单同步 | Synchronized (JVM 会自动优化)、内置锁 |
高竞争、灵活控制 | ReentrantLock (可设置公平性)、显式锁 |
读多写少 | ReentrantReadWriteLock |
高并发读 | StampedLock(乐观读)、乐观锁 |
原子操作、无锁编程 | Atomic类+ CAS、乐观锁 |
九、 参考
1、 官网地址OpenJDK Wiki
wiki.openjdk.org/display/Hot...
2、 OpenJDK 官方文档 AQS JavaDoc
docs.oracle.com/en/java/jav...
3、 Doug Lea AQS 论文 (作者原始设计文档)
gee.cs.oswego.edu/dl/papers/a...
4、 OpenJDK 源代码 , GitHub AQS源码
5、 ARM官方文档
developer.arm.com/documentati...
搜索LDXR/STXR,即ARM的LL/SC实现,关键指令:
LDXR(Load-Exclusive,相当于 LL)
STXR(Store-Exclusive,相当于 SC)
6、 RISC-V官方文档
搜索 LR.W/SC.W,关键指令:
LR.W(Load Reserved,相当于 LL)
SC.W(Store Conditional,相当于 SC)
7、 PowerPC官方文档
openpowerfoundation.org/specificati...
搜索 lwarx/stwcx,关键指令:
lwarx(Load with Reserve,相当于 LL)
stwcx(Store Conditional Word,相当于 SC)