多线程配合工作时,当线程检测到某条件不满足时就休眠,直到别的线程将条件准备好,然后通过条件变量将其唤醒。
条件变量需要在互斥锁的配合下才能工作。
条件变量的创建步骤:
1、定义一个条件变量(全局变量)由于条件变量需要互斥锁的配合,所以还需要定义一个线程互斥锁。
2、初始化条件变量
3、使用条件变量
4、删除条件变量,也需要把互斥锁删除。
主线程对va变量循环+1,次线程发现va==5时,打印va的值并将va清0,如果va的值!=5就什么都不做
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <semaphore.h>
pthread_t ids[2];
int va = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond; // 定义一个条件变量
void my_exit(int sig)
{
for (int i = 0; i < 2; i++)
{
pthread_cancel(ids[i]);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
}
exit(0);
}
void *thread1(void *arg)
{
while (1)
{
pthread_mutex_lock(&mutex);
va++;
if (va == 5)
{
// 通知thread2打印,va 清零
// int pthread_cond_signal(pthread_cond_t * cond);
// pthread_cond_signal(&cond); // 只能唤醒一个线程
// int pthread_cond_broadcast(pthread_cond_t * cond);
pthread_cond_broadcast(&cond); // 广播唤醒所有因为该条件变量睡眠的线程
/**
* 功能:当线程将某个数据准备好时,就可以调用该函数去设置cond,表示条件准备好了,
* pthread_cond_wait检测到cond被设置后就不再休眠(被唤醒),线程继续运行,使用别的线程准备好的数据来做事。
* 当调用pthread_cond_wait函数等待条件满足的线程只有一个时,就是用pthread_cond_signal来唤醒,
* 如果说有好多线程都调用pthread_cond_wait在等待时,
* 使用int pthread_cond_broadcast(pthread_cond_t *cond);
* 它可以将所有调用pthread_cond_wait而休眠的线程都唤醒。
*/
}
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
void *thread2(void *arg)
{
while (1)
{
pthread_mutex_lock(&mutex);
while (va != 5)
{
// 阻塞睡眠 + 释放已加的锁
// int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
pthread_cond_wait(&cond, &mutex);
/**
* 功能:检测条件变量cond,如果cond没有被设置,表示条件还不满足,别人还没有对cond进行设置,
* 此时pthread_cond_wait会休眠(阻塞),直到别的线程设置cond表示条件准备好后,才会被唤醒。
* 返回值:成功返回0,失败返回非零错误号
* 参数
* - cond:条件变量
* - mutex:和条件变量配合使用的互斥锁
*/
}
printf("va == %d\n", va);
va = 0;
pthread_mutex_unlock(&mutex);
}
}
int main(int argc, char const *argv[])
{
signal(SIGINT, my_exit); // 释放条件变量
int ret;
void *(*p_func[2])(void *) = {thread1, thread2};
// int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
// 初始化条件变量
pthread_cond_init(&cond, NULL);
/**
* 功能
* 初始化条件变量,与互斥锁的初始化类似。
* pthread_cond_init(&cond, NULL); //第二个参数为NULL,表示不设置条件变量的属性。也可以直接初始化:
* pthread_cond_t cond = PTHREAD_COND_INITIALIZER;//与互斥锁的初始化的原理是一样的
* 返回值:成功返回0,失败返回非零错误号
* - cond:条件变量
* - attr:用于设置条件变量的属性,设置为NULL,表示使用默认属性
*/
for (int i = 0; i < 2; i++)
{
ret = pthread_create(ids + i, NULL, p_func[i], NULL);
if (ret < 0)
{
perror("pthread create error");
exit(1);
}
pthread_detach(ids[i]);
}
pause();
return 0;
}