Linux--线程同步与互斥之条件变量
来源:互联网 发布:监控软件大全 编辑:程序博客网 时间:2024/04/27 21:39
上篇博客讲了互斥量问题:http://blog.csdn.net/sayhello_world/article/details/67637858
就拿生产者-消费者为例,如果两个线程都有互斥锁,但是生产者生产的快,消费者消费的慢,这里我们会发现,消费者一直再消费此时生产者还没有产生东西。这就会导致消费者总是加锁进来再解锁出去。为了让两者同步,这里提出了条件变量。
条件变量是线程可用的另一种同步机制。互斥量用于上锁,条件变量则用于等待,并且条件变量总是需要与互斥量一起使用。
需要了解的函数:
初始化函数:
int pthread_cond_init(pthread_cond_t*restrict cond, const pthread_condattr_t *restrict attr);
pthread_cond_t cond =PTHREAD_COND_INITIALIZER;
等待函数:
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_destroy(pthread_cond_t*cond);
和Mutex的初始化和销毁类似,pthread_cond_init 函数初始化为Condition Variable,attr参数为NULL则表示缺省属性,pthread_cond_destroy函数销毁一个Condition Variable。如果ConditionVariable是静态分配的,也可以用宏定义PTHEAD_COND_INITIALIZER初始化,相当于 用pthread_cond_init函数初始化并且attr参数为NULL。
一个线程可以调用pthread_cond_wait在一个ConditionVariable上阻塞等待,这个函数做以下三步操作:
1. 释放Mutex
2. 阻塞等待
3. 当被唤醒时,重新获得Mutex并返回
基于此 我们实现生产者-消费者模式。
代码思想说明:
生产者生产数据插入链表 消费者从链表中读取数据,中间场所为链表。
当消费者读取数据的时候 他需要加锁解锁并且要等待生产者生产数据。
当生产者写入数据的时候 他应该向链表中插入元素并且给消费者一个信号。
321模型:
3种关系:生产者--- 生产者,消费者--- 消费者,生产者--- 消费者
2种角色:生产者,消费者
1种交易场所:链表
代码实现:
#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<assert.h>#include<pthread.h>typedef struct plist{ struct plist* next; int data;}node_t,*node_p,**node_pp;static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;static node_p malloc_node(int d){ node_p _n = (node_p)malloc(sizeof(node_t)); if(_n == NULL) { perror("malloc\n"); exit(1); } _n -> data = d; _n -> next = NULL; return _n;} static is_empty(node_p p){ return p->next == NULL?1:0;}static delete_node(node_p p){ if(p != NULL) { free(p); }}void init_list(node_pp p){ *p = malloc_node(0);}//头插void push_list(node_p p,int data){ node_p cur = malloc_node(data); cur ->next = p->next; p->next = cur;}//头删void pop_list(node_p p,int *d){ assert(p); assert(d); if(!is_empty(p)) { node_p temp = p->next; p->next = temp->next; *d = temp->data; delete_node(temp); }}//销毁链表void destroy_list(node_p p){ assert(p); int data; while(!is_empty(p)) { pop_list(p,&data); } delete_node(p);}void show_list(node_p p){ assert(p); while(p != NULL) { printf("%d ",p->data); p = p->next; } printf("\n");}static void *consumer(void *arg){ node_p phead = (node_p)arg; int data = 0; for(;;) { pthread_mutex_lock(&lock); //当链表为空的时候,消费者应该等待生产者。 while(is_empty(phead)) { printf("consumer no data\n"); pthread_cond_wait(&cond,&lock); } pop_list(phead,&data); printf("consumer done:....%d\n",data); pthread_mutex_unlock(&lock); } return NULL;}static void *produce(void *arg){ node_p phead = (node_p)arg; int data = 0; for(;;) { pthread_mutex_lock(&lock); data = rand()%1234; push_list(phead,data); printf("produce data %d\n",data); pthread_mutex_unlock(&lock); //这里的sleep是为了让两者不同步,一个快一个慢。 sleep(1); pthread_cond_signal(&cond); printf("call consumer. preduce success val = %d\n",data); } return NULL;}int main(){ node_p phead = NULL; init_list(&phead); pthread_t p_produce; pthread_t p_consumer; pthread_create(&p_consumer,NULL,consumer,phead); pthread_create(&p_produce,NULL,produce,phead); pthread_join(p_consumer,NULL); pthread_join(p_produce,NULL); pthread_mutex_destroy(&lock); pthread_cond_destroy(&cond); destroy_list(phead); return 0;}
结果两者实现同步:
- Linux--线程同步与互斥之条件变量
- <linux线程>同步互斥机制之【条件变量】
- 【线程同步与互斥】条件变量
- Linux线程浅析[线程的同步和互斥之线程同步的条件变量pthread_cond_t]
- Linux 线程同步机制:互斥、读写锁、条件变量
- 条件变量---线程的同步与互斥
- 线程的同步与互斥:条件变量&信号量
- Linux入门:线程同步与互斥(二)——条件变量
- 线程同步(信号量,互斥,条件变量)
- Linux之线程:同步与互斥
- 【线程的同步与互斥 (互斥量 条件变量 信号量)】生产者与消费者模型
- Linux线程同步之条件变量
- Linux线程同步之条件变量
- Linux线程同步之条件变量
- Linux线程同步之条件变量
- Linux线程同步之条件变量
- linux 线程同步之条件变量
- Linux线程同步之条件变量
- python 爬取糗百
- python——一个投票器
- 搭建maven结构的web工程的时候,出现各种环境的问题的解决
- Java中的list---ArrayList与LinkedList
- 微信开发po类设计
- Linux--线程同步与互斥之条件变量
- PPT制作笔记
- Android代码获取xml中定义的dp\sp值的方法
- MultiByteToWideChar&WideCharToMultiByte 函数介绍
- 我用这种方法转载了“如何快速转载CSDN中的博客”这篇文章
- Java设计模式(一)----分类和原则
- addHeadView
- Spring MVC 在前端utf-8往后端传参数乱码处理
- 2的次方(c++)