插件窝 干货文章 linux实现线程同步有几种方式

linux实现线程同步有几种方式

pthread 线程 互斥 同步 317    来源:    2025-05-03

在 Linux 系统中,实现线程同步有多种方式,每种方式适用于不同的场景。以下是主要的线程同步方法及其特点:


1. 互斥锁 (Mutex)

  • 原理:通过锁机制确保同一时间只有一个线程访问共享资源。
  • APIc pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&mutex); // 加锁 pthread_mutex_unlock(&mutex); // 解锁
  • 特点
    • 简单高效,适用于短期锁定。
    • 可能引发死锁(需避免嵌套加锁或未释放锁)。

2. 读写锁 (Read-Write Lock)

  • 原理:允许多个读线程同时访问,但写线程独占资源。
  • APIc pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; pthread_rwlock_rdlock(&rwlock); // 读锁 pthread_rwlock_wrlock(&rwlock); // 写锁 pthread_rwlock_unlock(&rwlock); // 解锁
  • 特点
    • 读多写少的场景性能更优(如缓存系统)。

3. 条件变量 (Condition Variable)

  • 原理:线程等待某个条件成立时阻塞,条件满足时被唤醒。
  • APIc pthread_cond_t cond = PTHREAD_COND_INITIALIZER; pthread_cond_wait(&cond, &mutex); // 等待条件(需配合互斥锁) pthread_cond_signal(&cond); // 唤醒一个等待线程 pthread_cond_broadcast(&cond); // 唤醒所有等待线程
  • 特点
    • 必须与互斥锁配合使用。
    • 适用于生产者-消费者模型等场景。

4. 自旋锁 (Spinlock)

  • 原理:线程通过忙等待(Busy-Waiting)尝试获取锁。
  • APIc pthread_spinlock_t spinlock; pthread_spin_lock(&spinlock); // 自旋加锁 pthread_spin_unlock(&spinlock); // 解锁
  • 特点
    • 避免上下文切换,适合极短临界区(如内核态)。
    • 长时间等待会浪费CPU资源。

5. 屏障 (Barrier)

  • 原理:阻塞所有线程直到指定数量的线程到达同步点。
  • APIc pthread_barrier_t barrier; pthread_barrier_init(&barrier, NULL, n_threads); // 初始化 pthread_barrier_wait(&barrier); // 等待同步
  • 特点
    • 适用于多阶段并行计算(如MapReduce)。

6. 信号量 (Semaphore)

  • 原理:通过计数器控制线程访问资源数量。
  • APIc sem_t sem; sem_init(&sem, 0, initial_value); // 初始化 sem_wait(&sem); // P操作(减1) sem_post(&sem); // V操作(加1)
  • 特点
    • 可用于线程间或进程间同步。
    • 支持计数信号量(如限制资源池并发数)。

7. 文件锁 (fcntl/flock)

  • 原理:通过文件描述符实现跨进程同步。
  • APIc flock(fd, LOCK_EX); // 加排他锁 flock(fd, LOCK_UN); // 解锁
  • 特点
    • 适用于进程间同步(非纯线程场景)。

8. 原子操作 (Atomic Operations)

  • 原理:通过CPU指令保证操作的原子性(如CAS)。
  • API(GCC内置): c __sync_fetch_and_add(&counter, 1); // 原子加法
  • 特点
    • 无锁编程基础,性能极高。
    • 适用于简单计数器或标志位。

选择建议

场景 推荐方式
简单共享变量保护 互斥锁
读多写少 读写锁
等待条件触发 条件变量 + 互斥锁
极短临界区 自旋锁
多线程分阶段同步 屏障
控制资源池并发数 信号量
无锁高性能编程 原子操作

注意事项

  1. 避免死锁:按固定顺序获取多个锁,或使用 pthread_mutex_trylock
  2. 性能权衡:自旋锁 vs 互斥锁取决于临界区执行时间。
  3. 进程共享:部分同步对象需设置 PTHREAD_PROCESS_SHARED 属性。

通过合理选择同步机制,可以平衡线程安全性与系统性能。