原子变量控制临界区是否足够?正确实现方式问询
临界区控制的常见错误与正确实现
你这段代码确实没法正确实现临界区控制,核心问题在于检查someAtomicBool和设置它的操作不是原子性的,必然会引发竞态条件:
假设someAtomicBool初始值为true(你的逻辑应该是想让第一个进入的线程执行临界区,后续线程直接返回),当两个线程同时执行if (someAtomicBool) return;时,它们都可能读到true,然后都跳过return逻辑,接着都执行someAtomicBool = false;——最终两个线程都进入了临界区,完全起不到互斥的作用。
下面是两种可靠的实现方式:
方式1:使用互斥锁(最推荐)
这是最直观且不易出错的方案,直接用互斥锁包裹临界区:
#include <mutex> std::mutex critical_mutex; void enter_critical_section() { // lock_guard会自动在作用域结束时解锁,避免手动解锁的遗漏 std::lock_guard<std::mutex> lock(critical_mutex); // -------------------------- // 这里是你的临界区代码 // -------------------------- }
如果想实现“锁已被占用就直接返回”的逻辑,可以用try_lock:
#include <mutex> std::mutex critical_mutex; void try_enter_critical_section() { if (!critical_mutex.try_lock()) { // 锁已被占用,直接返回 return; } // 用adopt_lock接管已获取的锁,确保自动解锁 std::lock_guard<std::mutex> lock(critical_mutex, std::adopt_lock); // -------------------------- // 这里是你的临界区代码 // -------------------------- }
方式2:用原子操作的CAS(比较并交换)
如果不想依赖互斥锁,也可以用原子类型的compare_exchange_strong实现原子的检查-设置,从根源避免竞态:
#include <atomic> std::atomic<bool> is_critical_free = true; void try_enter_critical_section() { bool expected = true; // 原子性检查:如果当前值是expected,就改为false if (!is_critical_free.compare_exchange_strong(expected, false)) { // 交换失败,说明已有线程进入临界区 return; } // -------------------------- // 这里是你的临界区代码 // -------------------------- // 退出时记得将标记改回true,让其他线程可以进入 is_critical_free = true; }
CAS操作的整个检查-更新过程是原子的,不会被其他线程打断,能保证同一时间只有一个线程进入临界区。
内容的提问来源于stack exchange,提问作者bustus_primus
相关产品推荐
相关产品推荐

