关于std::atomic_flag实现自旋锁互斥的两个技术疑问
关于《C++ Concurrency in Action》自旋锁问题的解答
问题1:构造函数初始化与类内声明的差异
std::atomic_flag是不可拷贝、不可赋值的类型,其拷贝赋值运算符operator=被C++标准显式删除。
- 在构造函数中写
flag = ATOMIC_FLAG_INIT;属于赋值操作,试图调用已被删除的operator=,因此编译报错。 - 类内声明
std::atomic_flag flag = ATOMIC_FLAG_INIT;是初始化操作,并非赋值。ATOMIC_FLAG_INIT是标准定义的专用初始化器,用于将std::atomic_flag初始化为清除状态,这种写法属于编译器认可的直接初始化语法,不会触发赋值逻辑,因此可以正常编译。
问题2:单线程调用lock()时while循环未执行的原因
自旋锁的lock()逻辑通常基于std::atomic_flag::test_and_set()方法,典型实现如下:
void lock() { while (flag.test_and_set(std::memory_order_acquire)) { // 调试输出代码 } }
test_and_set()的核心行为是:原子性地将atomic_flag设为true,同时返回操作前的状态值。
- 单线程首次调用
lock()时,flag通过ATOMIC_FLAG_INIT初始化为清除状态(false)。调用test_and_set()后,flag被设为true,返回值为false,此时while条件不成立,循环体(包括调试输出)不会执行,直接进入临界区。 - 只有当
flag已处于设置状态(比如单线程未调用unlock()就再次调用lock()),test_and_set()才会返回true,while条件成立,循环体才会执行,你才能看到调试输出。
内容的提问来源于stack exchange,提问作者lips106
相关产品推荐
相关产品推荐

