在 Linux C++ 开发中,竞态条件(Race Condition)通常发生在多个线程或进程并发访问共享资源,且至少有一个是写操作,且缺乏同步机制时。下面从原理 → 常用手段 → 示例 → 最佳实践系统说明。
多个执行流 + 共享数据 + 非原子操作 + 缺少同步
例如:
int counter = 0;
// 线程A、B同时执行
counter++; // 非原子:读-改-写
最基础、最常用
#include <mutex>
std::mutex mtx;
int counter = 0;
void thread_func() {
std::lock_guard<std::mutex> lock(mtx);
counter++;
}
✅ 优点:简单、可靠
❌ 缺点:锁粒度大可能影响性能
适合简单变量
#include <atomic>
std::atomic<int> counter{0};
void thread_func() {
counter++; // 原子操作
}
✅ 无锁、性能高
❌ 仅适合简单类型和操作
读多写少场景
#include <shared_mutex>
std::shared_mutex rwlock;
int data = 0;
void read() {
std::shared_lock lock(rwlock);
// 读
}
void write() {
std::unique_lock lock(rwlock);
// 写
}
线程间等待/通知
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void worker() {
std::unique_lock lock(mtx);
cv.wait(lock, [] { return ready; });
}
#include <fcntl.h>
#include <unistd.h>
int fd = open("lockfile", O_CREAT | O_RDWR, 0666);
flock(fd, LOCK_EX);
// 临界区
flock(fd, LOCK_UN);
#include <semaphore.h>
sem_t *sem = sem_open("/mysem", O_CREAT, 0644, 1);
sem_wait(sem);
// 临界区
sem_post(sem);
g++ -fsanitize=thread -g main.cpp
./a.out
✅ 强烈推荐用于调试
最好的同步是不共享
thread_local int local_var;
✅ 尽量减少共享状态
✅ 使用消息队列 / 事件循环
✅ 函数无状态(可重入)
✅ 写操作集中管理(单写者模式)
if (counter == 0) { // 检查
counter++; // 再修改(已不安全)
}
应使用:
| 场景 | 推荐方式 |
|---|---|
| 简单计数 | atomic |
| 复杂结构 | mutex |
| 读多写少 | shared_mutex |
| 多进程 | 信号量 / 文件锁 |
| 调试检测 | TSan |
如果你有具体代码场景(线程?进程?共享什么数据?),我可以直接帮你改代码并分析竞态点。