线程同步是多线程编程中确保线程有序协作、避免竞态条件的关键机制。以下是常见的线程同步方式及其原理和应用场景:
一、基础锁机制
- 互斥锁 (Mutex)
- 原理:类似“厕所门锁”,同一时间仅允许一个线程进入临界区。
- 代码示例 (C++):
std::mutex mtx;
mtx.lock();
// 临界区操作
mtx.unlock();
- 适用场景:保护共享数据的读写操作。
- 读写锁 (Read-Write Lock)
- 原理:允许多个读线程并发,但写线程独占(读时共享,写时互斥)。
- 代码示例 (Java):
ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
rwLock.readLock().lock(); // 读锁
rwLock.writeLock().lock(); // 写锁
- 适用场景:读多写少的场景(如缓存系统)。
- 自旋锁 (Spinlock)
- 原理:线程通过循环忙等(while(locked))而非阻塞等待锁释放。
- 优势:避免上下文切换,适合短临界区。
- 风险:长时间自旋浪费CPU。
二、信号量 (Semaphore)
- 原理:维护一个计数器,控制同时访问资源的线程数量。
- P() (Wait):计数器减1,若<0则阻塞
- V() (Signal):计数器加1,唤醒等待线程
- 代码示例 (Python):
import threading
sem = threading.Semaphore(3) # 允许3个线程同时访问
def task():
sem.acquire()
# 访问资源(最多3线程并发)
sem.release()
- 应用场景:
- 限制数据库连接池并发数
- 生产者-消费者模型(控制缓冲区大小)
三、条件变量 (Condition Variable)
- 原理:让线程在条件不满足时主动阻塞,条件满足时被唤醒。必须与互斥锁配合使用。
- 关键操作:
- wait():释放锁并阻塞
- signal()/notify():唤醒一个等待线程
- broadcast()/notifyAll():唤醒所有等待线程
- 代码示例 (Java 生产者-消费者):
Lock lock = new ReentrantLock();
Condition notEmpty = lock.newCondition();
// 生产者
lock.lock();
try {
while (buffer.isFull())
notEmpty.await(); // 等待非空
buffer.add(item);
notFull.signal(); // 通知消费者
} finally { lock.unlock(); }
四、屏障 (Barrier)
- 原理:强制多个线程在屏障点等待,直到所有线程到达后才继续执行。
- 代码示例 (C#):
Barrier barrier = new Barrier(3); // 需等待3个线程
void Worker() {
// 阶段1操作
barrier.SignalAndWait(); // 等待所有线程完成阶段1
// 阶段2操作
}
- 应用场景:并行计算中多阶段任务同步(如MapReduce)。
五、原子操作 (Atomic Operations)
- 原理:通过CPU指令实现不可中断的单一操作(如CAS: Compare-And-Swap)。
- 优势:无锁同步,避免死锁和上下文切换。
- 代码示例 (C++):
std::atomic<int> counter(0);
counter.fetch_add(1); // 原子自增
- 典型类型:AtomicInteger、AtomicReference等。
六、其他高级同步机制
机制 | 描述 |
管程 (Monitor) | 语言级同步封装(如Java synchronized 关键字) |
Future/Promise | 异步任务结果同步(如Java Future.get() 阻塞至结果就绪) |
消息队列 | 通过传递消息解耦线程(如Go的Channel、Actor模型) |
读写屏障 | 控制内存访问顺序(如Java volatile 保证可见性) |
选择同步方式的考量因素
- 性能:自旋锁(短临界区) vs 互斥锁(长临界区)
- 复杂度:无锁编程 > 锁机制 > 高级抽象
- 公平性:是否需保证线程唤醒顺序(公平锁 vs 非公平锁)
- 场景适配:
- 互斥锁 → 简单数据保护
- 信号量 → 资源池限制
- 条件变量 → 多线程协作(生产者-消费者)
- 屏障 → 分阶段并行任务
最佳实践:优先使用高层抽象(如并发集合、异步框架),减少手动同步代码量;对性能敏感场景可深入底层锁或无锁编程。