线程同步之条件变量 生产者和消费者模型
条件变量
注意:需与互斥量一起使用,实现线程以互斥方式阻塞等待特定条件的发生(同步)
使用步骤:
- 定义条件变量
- 初始化条件变量,初始化互斥量
- 触发条件线程x:互斥量加锁->XX操作->触发条件变量->互斥量解锁
- 循环等待条件线程y:互斥量加锁->等待条件变量->XX操作->互斥量解锁。
注意:这里循环等待是避免等待线程由其他信号打断后被唤醒,需重新判断cond值。 - 销毁条件变量与互斥量变量
API函数:
-
初始化
静态:pthread_cond_t cond = PTHREAD_COND_INITIALIZER
动态:int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr)
参数1cond:条件变量
参数2attr:条件变量属性,若为NULL,则默认属性
成功返回0,失败返回错误码 -
销毁
Int pthread_cond_destroy(pthread_cond_t *cond)
参数为条件变量,成功返回0,失败返回错误码 -
等待条件变量与计时等待
Int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
参数1cond:条件变量
参数2mutex:互斥量
成功0,失败错误码(参数不正确) -
触发条件变量唤醒等待线程队列中的某一个线程
Int pthread_cond_signal(pthread_cond_t *cond)
成功0,失败错误码 -
触发条件变量唤醒等待线程队列中的所有线程,这些线程会进行竞争
Int pthread_cond_broadcast(pthread_cond_t *cond)
成功0,失败错误码
功能实现:进程中创建两个线程,线程A作为生产者循环不断生成数据,将数据加入单链表中,线程B作为消费者循环不断获取数据,并将该数据从链表中删除且释放空间。其中链表作为全部变量,以供两个线程操作。
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
//单链表模型
struct msg{
struct msg *next;
int num;
};
//表头
struct msg head = {
.next = NULL,
.num = 0,
};
pthread_cond_t has_product = PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
void *consumer(void *p)
{
struct msg *mp;
for(;;){
pthread_mutex_lock(&lock);
while(head.next == NULL)
pthread_cond_wait(&has_product, &lock);
mp = head.next;//从头部获取
head.next = mp->next;
pthread_mutex_unlock(&lock);
printf("Consume %d\n",mp->num);
free(mp);
sleep(rand()%5);
}
}
void *producer(void *p)
{
struct msg *mp,*pre;
pre = NULL;
for(;;){
//生成新结点
mp = malloc(sizeof(struct msg));
mp->num = rand() % 1000 + 1;//随机获取一个三位数的数据
mp->next = pre;
printf("Produce %d\n", mp->num);
pthread_mutex_lock(&lock);
head.next = mp;//采用头插法
pthread_cond_signal(&has_product);
pthread_mutex_unlock(&lock);
pre = mp;
sleep(rand() % 5);
}
}
int main(void)
{
pthread_t pid,cid;
//set the random arg
srand(time(NULL));
pthread_create(&pid, NULL, producer, NULL);
pthread_create(&cid, NULL, consumer, NULL);
pthread_join(pid,NULL);
pthread_join(cid,NULL);
return 0;
}
验证结果:
Produce 230
Produce 720
Consume 720
Consume 230
Produce 582
。。。
上一篇: 用C语言实现扫雷小游戏
下一篇: 扫雷游戏的简单实现