Z
ZHANK
编程在线教程C++ 教程互斥锁与原子操作
并发与模板进阶

互斥锁与原子操作

std::mutex/lock_guard、std::atomic、内存序、死锁避免

互斥锁与原子操作

数据竞争用锁或原子操作解决——std::mutex + std::lock_guard 是标配,std::atomic 更轻量。

学完本章你将: 掌握 std::mutex/lock_guard、std::atomic、死锁避免。


mutex + lock_guard

cpp
#include <mutex>

std::mutex mtx;
int counter = 0;

void increment() {
    for (int i = 0; i < 100000; i++) {
        std::lock_guard<std::mutex> lock(mtx);  // RAII 自动解锁
        counter++;
    }
}

std::thread t1(increment);
std::thread t2(increment);
t1.join(); t2.join();
std::cout << counter;  // 200000——正确!

std::atomic —— 无锁原子操作

cpp
#include <atomic>

std::atomic<int> counter{0};

void increment() {
    for (int i = 0; i < 100000; i++) {
        counter++;  // 原子操作——不需要锁,更高性能
    }
}
// 适用:简单计数、标志位
// 不适用:复杂数据结构(还是用 mutex)

死锁避免

cpp
std::mutex m1, m2;

// ❌ 死锁——两个线程以不同顺序获取锁
void f1() { lock(m1); lock(m2); }
void f2() { lock(m2); lock(m1); }

// ✅ 用 std::lock 同时获取多个锁
void safe() {
    std::lock(m1, m2);                     // 原子地锁定多个
    std::lock_guard<std::mutex> lk1(m1, std::adopt_lock);  // 接管已锁的 mutex
    std::lock_guard<std::mutex> lk2(m2, std::adopt_lock);
}

其他锁类型

cpp
std::shared_mutex smtx;   // C++17 读写锁
std::recursive_mutex rmtx; // 同一线程可多次 lock
std::timed_mutex tmtx;     // 带超时的锁