线程同步机制
外观
线程同步机制[编辑 | 编辑源代码]
线程同步机制是操作系统中协调多个线程对共享资源访问的重要方法,用于防止竞态条件(Race Condition)并确保数据一致性。当多个线程并发访问同一资源时,若无同步控制,可能导致数据损坏或逻辑错误。
核心问题[编辑 | 编辑源代码]
线程同步需解决以下三类问题:
- 互斥访问:确保同一时刻仅一个线程访问临界区(Critical Section)
- 执行顺序控制:线程间需按特定顺序执行(如生产者-消费者模型)
- 可见性:线程对共享变量的修改应对其他线程立即可见
同步原语[编辑 | 编辑源代码]
以下是主流操作系统提供的同步机制:
1. 互斥锁(Mutex)[编辑 | 编辑源代码]
最基本的同步工具,通过加锁/解锁操作实现临界区保护。
#include <pthread.h>
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
int shared_data = 0;
void* thread_func(void* arg) {
pthread_mutex_lock(&lock); // 进入临界区
shared_data++; // 安全修改共享数据
printf("Thread %ld: shared_data = %d\n", (long)arg, shared_data);
pthread_mutex_unlock(&lock); // 离开临界区
return NULL;
}
输出示例(两个线程并发执行):
Thread 1: shared_data = 1 Thread 2: shared_data = 2
2. 信号量(Semaphore)[编辑 | 编辑源代码]
由Dijkstra提出的计数器同步机制,支持资源计数访问:
C语言实现:
#include <semaphore.h>
sem_t sem;
void* worker(void* arg) {
sem_wait(&sem); // P操作
// 访问受限资源
sem_post(&sem); // V操作
return NULL;
}
3. 条件变量(Condition Variable)[编辑 | 编辑源代码]
用于线程间事件通知,常与互斥锁配合使用:
import threading
condition = threading.Condition()
queue = []
def consumer():
with condition:
while not queue:
condition.wait() # 自动释放锁并等待
item = queue.pop(0)
print(f"Consumed {item}")
def producer(item):
with condition:
queue.append(item)
condition.notify() # 唤醒等待线程
高级同步机制[编辑 | 编辑源代码]
机制 | 描述 | 适用场景 |
---|---|---|
读写锁 | 允许多读单写 | 读多写少场景 |
屏障(Barrier) | 等待所有线程到达同步点 | 并行计算 |
自旋锁 | 忙等待而非阻塞 | 短期等待场景 |
实际应用案例[编辑 | 编辑源代码]
数据库连接池实现需要:
- 使用互斥锁保护连接队列
- 信号量控制最大连接数
- 条件变量实现连接等待
典型错误示例(未同步导致竞态条件):
// 错误的多线程计数器
class UnsafeCounter {
private int count = 0;
public void increment() { count++; }
public int get() { return count; }
}
修正方案:
// 使用AtomicInteger解决
import java.util.concurrent.atomic.AtomicInteger;
class SafeCounter {
private AtomicInteger count = new AtomicInteger(0);
public void increment() { count.incrementAndGet(); }
public int get() { return count.get(); }
}
数学原理[编辑 | 编辑源代码]
同步机制的 correctness 可通过以下性质验证:
- 安全性(Safety):
- 活性(Liveness):
其中表示临界区,表示"最终"时序运算符。
性能考量[编辑 | 编辑源代码]
同步操作可能引发:
- 上下文切换开销(互斥锁)
- CPU空转(自旋锁)
- 线程唤醒延迟(条件变量)
优化策略包括:
- 减小临界区范围
- 使用无锁数据结构
- 采用读写分离设计
页面模块:Message box/ambox.css没有内容。
过度同步会导致性能下降,需在正确性和效率间权衡 |