1.概念
线程中的一个概念,和进程中的信号的概念很像,等待某一个条件的发生。条件变量可以使得线程睡眠以等待某种条件的发生。它是利用线程间共享的全局变量进行线程间同步的一种机制,主要包含两个动作:线程为等待其他线程的某个条件成立而挂起,线程满足了某个条件而向其他线程发出信号。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。条件变量会造成线程阻塞,它作为一个线程之间通信的方式,给多线程提供了一个会合的场所。
2.相关主要函数及变量类型
头文件:
#include <pthread.h>
函数定义:
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);// 初始化一个条件变量
int pthread_cond_destroy(pthread_cond_t *cond);//销毁一个条件变量
int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime);//限时等待一个条件变量
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);//阻塞等待一个条件变量
int pthread_cond_broadcast(pthread_cond_t *cond);//当条件变量满足时,该函数可唤醒阻塞在条件上的所有线程
int pthread_cond_signal(pthread_cond_t *cond);//当条件变量满足时,该函数可唤醒阻塞在条件上的至少一个线程
返回值:
上面6个函数的返回值都是成功返回0,失败直接返回错误号。
pthread_cond_t类型,用于定义条件变量.
pthread_cond_wait函数说明(阻塞等待一个条件变量,永久阻塞,可比照sigsuspend函数进行学习):
函数的作用:
1.阻塞等待条件变量cond满足;
2.释放已掌握的互斥锁(解锁互斥量),相当于pthread_mutex_unlock(&mutex);(1,2两步是个原子操作)
3.当被唤醒时,pthread_cond_wait函数返回时,解除阻塞并且重新申请获取互斥锁pthread_mutex_lock(&mutex)
在调用pthread_cond_wait之前要有:
(1)定义互斥量和条件变量;
(2)初始化互斥量和条件变量,对互斥量加锁;
pthread_cond_timedwait-限时等待一个条件变量(在一定的时间内是阻塞的)
3.线程同步的经典模型
生产者消费者模型
4.编码演示
/*
作者:Muten
编码时间:20201016
编码目的:演示借助线程中利用条件变量模拟【生产者消费者】问题
代码功能:借助条件变量模拟【生产者消费者】问题
*/
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
struct msg
{
struct msg *next;
int num;
};
struct msg *head;
struct msg *mp;
/*静态方式初始化一个条件变量和一个互斥量*/
pthread_cond_t has_product = PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
void *consumer(void* p)
{
for(;;)
{
pthread_mutex_lock(&lock);
while(head == NULL)// 头结点为空说明没有节点
{
pthread_cond_wait(&has_product,&lock);//一旦调用pthread_cond_wait会放弃lock这个互斥量
}
mp = head;
head = mp->next;
pthread_mutex_unlock(&lock);
printf("--Consumer----%d.\n",mp->num);
free(p);
p = NULL;
sleep(rand()%5);
}
}
//生产者县线程调用的函数
void *producer(void* p)
{
for(;;)
{
mp = malloc(sizeof(struct msg));
mp->num = rand()%1000 +1;
printf("--Producer----%d.\n",mp->num);
pthread_mutex_lock(&lock);//这里可以执行成功,消费者一旦调用pthread_cond_wait就把这个互斥量解锁了,所以这里可以可以正常获取互斥锁
mp->next = head;
head = mp;//头插法
pthread_mutex_unlock(&lock);
pthread_cond_signal(&has_product);
sleep(rand()%5);
}
}
int main()
{
pthread_t pid ,cid;
srand(time(NULL));
pthread_create(&pid,NULL,producer,NULL);
pthread_create(&pid,NULL,consumer,NULL);
pthread_join(pid,NULL);
pthread_join(pid,NULL);
return 0;
}
5.条件变量的优点
其实只有mutex已经能够完成我们对共享资源的保护,但为什么又衍生出条件变量和读写锁这些机制呢?这是为了在合适的场景下进一步优化我们的处理流程,使得程序更高效。
相较于mutex而言,条件变量可以减少竞争。我们针对上面的生产者消费者模型来分析,如果直接使用mutex,除了生产者消费者之间需要竞争
互斥量以外,消费者之间也需要竞争互斥量,但如果共享资源中不存在数据,消费者之间竞争互斥锁是没有意义的。有了条件变量机制以后,
只有生产者完成生产,才会引起消费者之间的竞争,提高了程序效率。
本文介绍了线程中的条件变量,一种用于线程间同步的机制,通过等待和信号操作实现线程间的协作。条件变量通常与互斥锁结合使用,避免竞争条件。在生产者消费者模型中,条件变量能减少不必要的锁竞争,提高程序效率。文中还给出了使用pthread库实现的条件变量示例代码,展示了如何在多线程环境中解决生产者消费者问题。
819

被折叠的 条评论
为什么被折叠?



