在C++中,线程同步是确保多个线程在访问共享资源时能够协调一致的重要概念。以下是一些常用的线程同步方法:
1. 互斥锁(Mutexes)
互斥锁用于保护共享资源不被多个线程同时访问。当一个线程需要访问共享资源时,它必须先锁定互斥锁,访问完毕后再解锁。
```cpp
#include <mutex>
std::mutex mtx;
void safeFunction() {
std::lock_guard<std::mutex> lock(mtx);
// 临界区:在这个代码块中,mtx 被锁定
}
```
2. 条件变量(Condition Variables)
条件变量用于线程间的协调,允许一个或多个线程在某些条件满足之前挂起,并在条件满足时被唤醒。
```cpp
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
void waitingFunction() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, []{ return some_condition; });
// 当 some_condition 为真时,线程被唤醒
}
```
3. 自旋锁(Spinlocks)
自旋锁是一种忙等待的锁,当锁被占用时,线程会循环检查锁是否已被释放,而不是真正挂起。适用于锁持有时间短且线程不希望在等待期间放弃CPU的场景。
```cpp
#include <atomic>
std::atomic_flag spinlock = ATOMIC_FLAG_INIT;
void spinningFunction() {
while (spinlock.test_and_set(std::memory_order_acquire)) { /* 忙等待 */ }
// 临界区
spinlock.clear(std::memory_order_release);
}
```
4. 读写锁(Read-Write Locks)
读写锁允许多个线程同时读取资源,但在写入资源时需要独占访问。这在读取操作远多于写入操作的场景中非常有用。
```cpp
#include <shared_mutex>
std::shared_mutex rw_mutex;
void readFunction() {
std::shared_lock<std::shared_mutex> lock(rw_mutex);
// 临界区:多个线程可以同时读取
}
void writeFunction() {
std::unique_lock<std::shared_mutex> lock(rw_mutex);
// 临界区:写入时独占访问
}
```
5. 原子操作(Atomic Operations)
原子操作确保变量的某些操作是不可分割的,即使在多线程环境中也不会被中断。
```cpp
#include <atomic>
std::atomic<int> atomic_var(0);
void atomicFunction() {
atomic_var.fetch_add(1, std::memory_order_relaxed);
}
```
6. 信号量(Semaphores)
信号量是一种计数器,可以用来控制对共享资源的访问数量。
```cpp
#include <semaphore>
std::counting_semaphore<> semaphore(1);
void semaphoreFunction() {
semaphore.acquire();
// 临界区
semaphore.release();
}
```
7. 屏障(Barriers)
屏障是一种同步机制,允许多个线程等待,直到所有线程都到达屏障点后再继续执行。
```cpp
#include <barrier>
std::barrier barrier(2);
void barrierFunction() {
// ...
barrier.wait(); // 等待其他线程到达屏障
// ...
}
```
8. 线程局部存储(Thread Local Storage, TLS)
线程局部存储允许每个线程拥有其私有的变量副本,从而避免了线程间的同步问题。
```cpp
thread_local int threadLocalVar = 0;
void tlsFunction() {
threadLocalVar++; // 每个线程修改自己的副本
}
```
9. 异步任务(Asynchronous Tasks)
使用 `std::async` 可以启动异步任务,它可能在新线程中运行,并且可以等待其结果。
```cpp
std::future<int> result = std::async(std::launch::async, someFunction);
int value = result.get(); // 等待异步任务完成并获取结果
```
10. 锁的其他变体
C++ 标准库还提供了其他类型的锁,如 `recursive_mutex`(允许同一个线程多次锁定)和 `timed_mutex`(支持带超时的锁定尝试)。