引言:为什么需要无锁编程
在多核时代,并发性能是系统架构的核心命题。传统的互斥锁(mutex)虽然简单可靠,但在高竞争场景下存在固有缺陷:线程阻塞唤醒的上下文切换开销、优先级反转、死锁风险,以及无法在信号处理程序或中断上下文中使用等问题。无锁编程(Lock-Free Programming)作为一种更精细的并发控制手段,通过硬件提供的原子指令实现线程间同步,避免了操作系统层面的阻塞,为极致性能场景提供了可能。
需要明确的是,"无锁"不等于"无等待"。无锁保证至少一个线程在有限步骤内完成操作,但个别线程可能因竞争失败而重试。本文将从底向上,系统讲解无锁编程的核心机制。
一、原子操作基石
1.1 缓存一致性与总线锁
现代多核处理器中,每个核心拥有独立的L1/L2缓存。当多个核心访问同一内存地址时,需要缓存一致性协议(如MESI)保证数据可见性。原子操作的实现依赖于两种机制:
总线锁(Bus Lock):LOCK#信号锁定整个内存总线,简单粗暴但粒度大,性能差。现代x86仅在跨缓存行(Split Lock)等特殊场景使用。
缓存锁(Cache Lock):利用MESI协议的Modified/Exclusive状态,仅锁定目标缓存行。这是CAS等原子指令的主要实现方式。
1.2 CAS操作详解
Compare-And-Swap是最基础的原子原语:
// CAS 伪代码
bool CAS(int* ptr, int expected, int desired) {
atomic {
if (*ptr == expected) {
*ptr = desired;
return true;
}
return false;
}
}
x86平台对应CMPXCHG指令(带LOCK前缀),ARM平台使用LDXR/STXR独占加载/存储对实现LL/SC(Load-Linked/Store-Conditional)模型。
典型使用模式——乐观重试:
void atomic_increment(atomic_int* counter) {
int old_val, new_val;
do {
old_val = atomic_load(counter);
new_val = old_val 1;
} while (!atomic_compare_exchange_weak(counter,

发表评论 取消回复