线程同步机制总结
条件变量机制
-
作用与特点
• 用于线程间同步,允许线程以无竞争方式等待特定条件的发生,避免忙等待(轮询)造成的CPU资源浪费。
• 需与互斥锁(pthread_mutex_t
)配合使用,确保对共享条件的检查在互斥锁保护下进行。
• 条件变量本身不保存状态信息,仅提供阻塞和唤醒机制。 -
核心操作流程
- 初始化
◦ 静态初始化:pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
◦ 动态初始化:pthread_cond_init(&cond, NULL);
- 等待条件
◦ 调用pthread_cond_wait(cond, mutex)
:
▪ 自动释放互斥锁mutex
,线程进入阻塞等待状态。
▪ 被唤醒后重新获取mutex
锁,需再次检查条件是否满足(防止虚假唤醒)。 - 通知条件
◦pthread_cond_signal(cond)
:唤醒至少一个等待线程。
◦pthread_cond_broadcast(cond)
:唤醒所有等待线程。 - 销毁:
pthread_cond_destroy(&cond)
。
- 初始化
-
关键函数
函数 描述 pthread_cond_init()
动态初始化条件变量 pthread_cond_wait()
阻塞等待条件,释放锁 pthread_cond_signal()
唤醒一个等待线程 pthread_cond_broadcast()
唤醒所有等待线程 pthread_cond_destroy()
销毁条件变量 -
典型应用场景
• 生产者-消费者模型:当缓冲区为空时,消费者线程等待;生产者填充数据后通知消费者。
信号量机制
-
作用与特点
• 用于控制对共享资源的访问,支持线程/进程间的同步和互斥。
• 信号量是一个非负整数计数器,通过PV原子操作(P:申请资源,V:释放资源)实现同步。
• 与条件变量不同,信号量本身保存状态(计数值),常用于资源池管理。 -
PV原子操作原理
• P操作(sem_wait
):
◦ 若信号量值 > 0,减1并继续执行。
◦ 若值 = 0,阻塞直到其他线程执行V操作。
• V操作(sem_post
):
◦ 信号量值加1,唤醒等待的线程(如果有)。 -
信号量类型
• 二进制信号量:值范围为0或1,用于互斥(类似互斥锁)。
• 计数信号量:值 >=0,表示可用资源数量,用于同步(如生产者-消费者)。 -
应用模式
• 互斥:
◦ 初始化信号量为1,线程进入临界区前执行P操作,退出后执行V操作。sem_t mutex; sem_init(&mutex, 0, 1); // 初始值1 // 线程1 sem_wait(&mutex); // 临界区操作 sem_post(&mutex); // 线程2同理
• 同步:
◦ 使用多个信号量协调线程执行顺序。例如,设置sem1=0
,sem2=1
,线程A执行完触发sem_post(sem1)
,线程B等待sem_wait(sem1)
。sem_t sem1, sem2; sem_init(&sem1, 0, 0); // 初始值0 sem_init(&sem2, 0, 1); // 初始值1 // 线程A sem_wait(&sem2); // 操作1 sem_post(&sem1); // 线程B sem_wait(&sem1); // 操作2 sem_post(&sem2);
-
关键函数
函数 描述 sem_init()
初始化信号量 sem_wait()
P操作,申请资源 sem_post()
V操作,释放资源 sem_destroy()
销毁信号量 sem_getvalue()
获取信号量当前值 -
典型应用场景
• 哲学家就餐问题:通过信号量控制筷子资源的获取,避免死锁。
• 生产者-消费者问题:用计数信号量管理缓冲区空/满状态。
对比与总结
机制 | 适用场景 | 核心特点 |
---|---|---|
条件变量 | 等待特定条件成立 | 需搭配互斥锁,自动释放锁避免死锁 |
信号量 | 资源计数/互斥 | 自带计数器,无需显式锁,支持更复杂的同步逻辑 |
选择建议:
• 若需等待某个复杂条件,优先使用条件变量。
• 若需管理资源数量(如线程池、缓冲区),优先使用信号量。