(一)条件变量
条件变量提供一种线程间通知机制,当某个共享数据到达一定条件时,会唤醒等待(阻塞的)得到这个共享数据的线程
条件变量与互斥锁结合使用,对临界区资源加锁进行控制的基础上,当条件变量满足条件,会唤醒该线程;执行完毕后解锁;
(二)条件变量的相关接口
头文件: pthread.h
(1)初始化条件变量
int pthread_cond_init(pthread_cond_t* cond, pthread_condattr_t* attr);
(2)把某个线程添加到条件变量的等待队列(一种数据结构如:链表)中,等待条件可用
int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex);
注意:
- 在使用pthread_cond_wait的前后应该加锁控制
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
将线程添加到条件变量的等待队列之前,防止其他线程的添加到条件变量的等待队列产生覆盖
(3)唤醒单个线程
int pthread_cond_signal(pthread_cond_t* cond);
(4)唤醒所有等待的线程
int pthread_cond_broadcast(pthread_cond_t* cond);
3 4 的前后使用互斥锁进行控制
防止唤醒线程的过程中有其他的线程入队/出队
(5)销毁条件变量
int pthread_cond_destroy(pthread_cond_t* cond);
(三)简单使用条件变量
功能描述:
- 主线程从键盘获取字符串后,唤醒两个新进程其中一个线程输出字符串打印到屏幕上
- 若输入end开头的字符串,结束所有的线程。
注意点:需要用互斥锁控制的点
多个线程同时进出等待队列
唤醒的过程中有进出等待队列
- 代码:
#include <stdio.h>
#include <pthread.h>
#include <string.h>
//创建互斥锁
pthread_mutex_t mutex;
//创建条件变量
pthread_cond_t cond;
void* print_fun1(void* arg)
{
char* s = (char*)arg;
while(1)
{
//加互斥锁
pthread_mutex_lock(&mutex);
//添加条件变量到等待队列
pthread_cond_wait(&cond, &mutex);
//解互斥锁
pthread_mutex_unlock(&mutex);
if(strncmp(s, "end", 3) == 0)
{
break;
}
printf("fun1 = %s\n", s);
}
pthread_exit(NULL);
}
void* print_fun2(void* arg)
{
char* s = (char*)arg;
while(1)
{
//加互斥锁
pthread_mutex_lock(&mutex);
//添加条件变量到等待队列
pthread_cond_wait(&cond, &mutex);
//解互斥锁
pthread_mutex_unlock(&mutex);
if(strncmp(s, "end", 3) == 0)
{
break;
}
printf("fun2 = %s\n", s);
}
pthread_exit(NULL);
}
int main()
{
//初始化互斥锁
pthread_mutex_init(&mutex, NULL);
//初始化条件变量
pthread_cond_init(&cond, NULL);
pthread_t ids[2];
char buff[128] = {
0};
pthread_create(&ids[0], NULL, print_fun1, (void*)buff);
pthread_create(&ids[1], NULL, print_fun2, (void*)buff);
while(1)
{
fgets(buff, 127, stdin);
buff[strlen(buff) - 1] = '\0';
if(strncmp(buff, "end", 3) == 0)
{
//防止唤醒时,等待队列有进出的线程
pthread_mutex_lock(&mutex);
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
break;
}
//防止唤醒时,等待队列有进出的线程
pthread_mutex_lock(&mutex);
//输入完成后去唤醒某个线程
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
//等待其他线程退出
for(int i = 0; i < 2; i++)
{
pthread_join(ids[i], NULL);
}
//销毁锁
pthread_mutex_destroy(&mutex);
//销毁条件变量
pthread_cond_destroy(&cond);
return 0;
}
- 结果: