锁和原子变量的基础介绍
1. 锁(Mutex)的基本概念
什么是锁?
锁是一种同步机制,用于保护共享资源,确保在同一时间只有一个线程可以访问这些资源。
基本使用方式:
cpp
#include <mutex>std::mutex mtx; // 声明一个互斥锁void critical_section() {mtx.lock(); // 获取锁// ... 访问共享资源的代码mtx.unlock(); // 释放锁
}
更安全的方式 - 使用锁守卫:
cpp
void critical_section() {std::lock_guard<std::mutex> lock(mtx); // 构造时自动加锁// ... 访问共享资源的代码// 析构时自动解锁,即使发生异常也能保证解锁
}
更灵活的方式 - 使用unique_lock:
cpp
void critical_section() {std::unique_lock<std::mutex> lock(mtx); // 构造时自动加锁// ... 访问共享资源的代码// 可以手动解锁,也可以等待条件变量lock.unlock(); // 手动解锁// ... 其他不需要锁的操作lock.lock(); // 重新加锁
}
2. 条件变量(Condition Variable)
什么是条件变量?
条件变量允许线程在某个条件不满足时等待,当条件满足时被其他线程唤醒。
基本使用模式:
cpp
#include <condition_variable>std::mutex mtx;
std::condition_variable cv;
bool ready = false;// 等待线程
void waiting_thread() {std::unique_lock<std::mutex> lock(mtx);while (!ready) { // 必须用循环检查条件cv.wait(lock); // 等待时会释放锁,被唤醒时重新获取锁}// 条件满足,执行操作
}// 通知线程
void notifying_thread() {{std::lock_guard<std::mutex> lock(mtx);ready = true;}cv.notify_one(); // 或 cv.notify_all()
}
3. 原子变量(Atomic Variables)
什么是原子变量?
原子变量提供了一种无需锁就能进行线程安全操作的方式,操作是不可中断的。
基本使用:
cpp
#include <atomic>std::atomic<int> counter(0); // 原子整型void increment() {counter++; // 原子操作,线程安全
}void complex_operation() {// 非原子操作需要额外处理int expected = counter.load();while (!counter.compare_exchange_weak(expected, expected + 1)) {// 如果counter的值不等于expected,更新expected并重试}
}
原子操作的优势:
-
性能更好(无锁操作)
-
不会发生死锁
-
适用于简单的计数器、标志位等
