在多线程编程中,线程同步是保证数据一致性和避免竞态条件的关键。以下是常见的线程同步机制:
- 互斥锁 (Mutex)
– 定义: 确保同一时间只有一个线程访问共享资源。
- 使用场景: 保护临界区代码或共享数据。
-
示例:
pthread_mutex_t lock;
pthread_mutex_init(&lock, NULL);
pthread_mutex_lock(&lock);
// 临界区操作
pthread_mutex_unlock(&lock);
- 信号量 (Semaphore)
– 定义: 计数器控制多个线程对资源的访问。
- 类型:
-
二进制信号量 (类似互斥锁)
-
计数信号量 (限制并发线程数量)
-
示例:
sem_t sem;
sem_init(&sem, 0, 5); // 初始值5
sem_wait(&sem); // 申请资源
// 访问资源
sem_post(&sem); // 释放资源
- 条件变量 (Condition Variable)
– 定义: 允许线程在特定条件满足时唤醒其他线程。
- 依赖: 必须与互斥锁配合使用。
-
示例:
pthread_cond_t cond;
pthread_mutex_t mutex;
// 线程A等待条件
pthread_mutex_lock(&mutex);
while (condition_not_met) {
pthread_cond_wait(&cond, &mutex);
}
// 执行操作
pthread_mutex_unlock(&mutex);
// 线程B通知条件变化
pthread_cond_signal(&cond);
- 读写锁 (Read-Write Lock)
-
定义: 区分读锁(共享)和写锁(独占)。
-
适用场景: 读多写少的数据访问。
-
示例:
pthread_rwlock_t rwlock;
pthread_rwlock_rdlock(&rwlock); // 读锁
// 读取数据
pthread_rwlock_unlock(&rwlock);
pthread_rwlock_wrlock(&rwlock); // 写锁
// 修改数据
pthread_rwlock_unlock(&rwlock);
- 自旋锁 (Spinlock)
– 定义: 线程忙等待锁释放,不进入睡眠状态。
- 适用场景: 锁持有时间极短的场景。
-
注意: 可能浪费CPU资源。
-
示例:
spinlock_t lock;
spin_lock(&lock);
// 临界区操作
spin_unlock(&lock);
- 屏障 (Barrier)
– 定义: 使多个线程在指定点同步等待。
- 适用场景: 并行计算分阶段处理。
-
示例:
pthread_barrier_t barrier;
pthread_barrier_init(&barrier, NULL, 3); // 等待3个线程
// 线程执行到屏障点等待
pthread_barrier_wait(&barrier);
- 原子操作 (Atomic Operations)
– 定义: 通过硬件支持的不可中断操作保证数据一致性。
- 示例 (C11):
#include <stdatomic.h>
atomic_int counter = ATOMIC_VAR_INIT(0);
atomic_fetch_add(&counter, 1); // 原子加法
- 事件 (Event)
– 定义: 通知机制(如Windows API)。
- 示例:
HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);
// 等待事件
WaitForSingleObject(event, INFINITE);
// 触发事件
SetEvent(event);
- 线程局部存储 (Thread-Local Storage, TLS)
– 定义: 每个线程拥有独立变量副本。
-
适用场景: 避免共享数据的同步问题。
-
示例 (C++11):
thread_local int thread_specific_data = 0;