1,条件变量
条件变量非常类似于JS里的信号:
- 线程A阻塞着等待条件变量变为真(监听信号);
- 线程B发出通知已满足条件(触发信号);
- 线程A解除阻塞开始后面的操作(响应信号)
与之对应的,我们需要一些类型和接口来监听、触发信号。
条件变量的类型:pthread_cond_t
使用前需要进行初始化:
int pthread_cond_init(pyhread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pyhread_cond_t *cond);
监听信号:
int pthread_cond_wait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex);
触发信号:
int pthread_cond_signal(pthread_cond_t *cond); //至少唤醒一个线程
int pthread_cond_broadcast(pthread_cond_t *cond);//广播,唤醒所有线程
因为有可能多个线程都在监听同一个信号,所以条件变量通常都是跟互斥锁配合使用,防止发生竞争。
条件变量利用了每个线程都可读写进程的全局变量这一特性。所以我们通常把条件变量定义成全局变量。
2,例子
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
//进程的全局变量,每个线程都可以读写
pthread_mutex_t mutex; //保护条件变量的互斥锁
pthread_cond_t cond; //条件变量
void *thread1(void *arg);
void *thread2(void *arg);
int main(){
//11.6.6 条件变量
pthread_t thid1, thid2;
pthread_mutex_init(&mutex, NULL); //初始化互斥锁
pthread_cond_init(&cond, NULL); //初始化条件变量
//创建两个线程
pthread_create(&thid1, NULL, thread1, NULL);
pthread_create(&thid2, NULL, thread2, NULL);
sleep(3); //防止在线程创建完成前就触发信号
//发信号
pthread_cond_signal(&cond);//触发一次
sleep(3);
pthread_cond_signal(&cond);//触发两次
sleep(3);
exit(0);
}
执行结果:
➜ code g++ -g -W -o study_Linux study_Linux.c -lpthread
➜ code ./study_Linux
thread1 is running
thread2 is running
thread1 applied the condition
thread2 applied the condition
可见,pthread_cond_signal一次只唤醒了一个线程。