面试官提问:
如果让你自己实现一个 mutex
互斥锁,你会怎么设计它?请说明核心原理和关键函数的实现。
应聘者参考回答:
实现一个互斥锁的核心在于正确实现其 lock()
和 unlock()
方法,以保证临界区在任意时刻只能被一个线程访问。我的实现思路如下:
一、核心原理:基于 Test-and-Set 的自旋锁
- 使用一个原子变量
flag
表示锁的状态:flag = 0
表示当前未加锁,线程可进入临界区;flag = 1
表示当前已加锁,其他线程需等待。
- 利用原子操作
TestAndSet()
来保证并发访问时的互斥性。
二、关键方法实现
// 原子操作:测试并设置
int TestAndSet(int *ptr, int newValue) {
int old = *ptr;
*ptr = newValue;
return old;
}
// 全局锁状态标志,初始为未锁定
static int flag = 0;
void lock() {
// 自旋等待直到 flag 被成功置为 1
while (TestAndSet(&flag, 1) == 1) {
// busy wait,直到其他线程释放锁
}
}
void unlock() {
// 释放锁
flag = 0;
}
三、说明与优化方向
- 由于使用
while
循环等待锁释放,这种锁属于自旋锁,适用于临界区短、线程竞争不激烈的场景; - 若要优化为在锁长时间持有时不浪费 CPU,可进一步结合
futex
或条件变量
实现阻塞等待; - 需要确保
TestAndSet
是原子操作,通常通过汇编指令(如xchg
)或使用 C++11 的std::atomic
实现。
这种最基础的 mutex
实现体现了并发控制的底层原理,是理解现代锁机制如 std::mutex
、pthread_mutex_t
的基础。
😀 关注 @公众号 程序员陈子青,获取更多 C++ 技术支持。