linux线程学习(4)
来源:互联网 发布:java报表打印 编辑:程序博客网 时间:2024/06/05 11:57
线程的同步
1. 条件变量
提供线程之间的一种通知机制,当某一条件满足时,线程A可以通知阻塞在条件变量上的线程B,B所期望的条件已经满足,可以解除在条件变量上的阻塞操作,继续做其他事情。
我们需要这种机制,当互斥量被锁住以后发现当前线程还是无法完成自己的操作,那么它应该释放互斥量,让其他线程工作。
1、可以采用轮询的方式,不停的查询你需要的条件
2、让系统来帮你查询条件,使用条件变量pthread_cond_t cond
2. 条件变量的初始化和销毁
//条件变量使用之前需要初始化pthread_cond_t cond = PTHREAD_COND_INITIALIZER;int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr); // 默认属性为空NULL//条件变量使用完成之后需要销毁int pthread_cond_destroy(pthread_cond_t *cond);
3. 条件变量的使用
//条件变量使用需要配合互斥量int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);//1、使用pthread_cond_wait等待条件变为真。传递给pthread_cond_wait的互斥量对条件进行保护,调用者把锁住的互斥量传递给函数。//2、这个函数将线程放到等待条件的线程列表上,然后对互斥量进行解锁,这是个原子操作。当条件满足时这个函数返回,返回以后继续对互斥量加锁。
当条件满足的时候,需要唤醒等待条件的线程
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
1、pthread_cond_broadcast唤醒等待条件的所有线程
2、pthread_cond_signal至少唤醒等待条件的某一个线程
注意,一定要在条件改变以后在唤醒线程
4. 实例练习
创建两个线程,一个线程往buff里写数据,每隔1s写一次,总共写30次,一个线程往buff里读数据,每隔2s读一次,总共读30次:
#include <pthread.h>#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <errno.h>#define BUFF_SIZE 5typedef struct product{ int buff[BUFF_SIZE];//数据buff int readpos,writepos;//读写位置,即buff的下标 pthread_mutex_t lock;//互斥量,配合条件变量使用 pthread_cond_t notempty;//非空条件 pthread_cond_t notfull;//非满条件}*Buff_t;void put(Buff_t p,int data);int get(Buff_t p);//进行互斥量、条件变量、位置(下标)的初始化void init_func(Buff_t p){ pthread_mutex_init(&(p->lock),NULL);//互斥量初始化 //条件变量初试化 pthread_cond_init(&(p->notempty),NULL); pthread_cond_init(&(p->notfull),NULL); //初始化时读和写的位置(下标)均为零 p->readpos=0; p->writepos=0;}//函数功能:进行互斥量、条件变量的销毁void destory(Buff_t p){ pthread_mutex_destroy(&p->lock); pthread_cond_destroy(&p->notempty); pthread_cond_destroy(&p->notfull); p->readpos=0; p->writepos=0;}void * producer(void *arg)//子线程生成,然后放入buff{ int i; for(i=1;i<=30;i++) { put((Buff_t)arg,i); printf("put the %d production to buff\n",i); sleep(1); printf("put the %d production to buff success\n",i); } return NULL;}void *customer(void *arg)//子线程消费,行buff去出相关值并打印{ int i,val; for(i=1;i<=30;i++) { val=get((Buff_t)arg); printf("get the production form buff\n"); sleep(2); printf("get the production form buff success,val is %d\n",val); } return NULL;}void put(Buff_t p,int data){ pthread_mutex_lock(&p->lock);//进行加锁操作 if((p->writepos+1)%BUFF_SIZE == p->readpos)//判断buff是否满了 { printf("producer wait for not full\n"); pthread_cond_wait(&p->notfull, &p->lock);//如果满了,就需要等待到非满的时候,等待时,互斥量会被解锁,其他有进行加锁的线程就可以运行(这里的等待时,get()函数就可运行),当条件满足时这个函数返回,返回以后继续对互斥量加锁。 } p->buff[p->writepos] = data;//buff非满时,就可往buff里写入数据, p->writepos = (p->writepos+1) % BUFF_SIZE;//写位置加一,当超过BUFF_SIZE时,要从头开始(即为零) pthread_cond_signal(&p->notempty);//发出非空信号,唤醒等待条件的线程 pthread_mutex_unlock(&p->lock);//解锁操作}int get(Buff_t p){ int val; pthread_mutex_lock(&p->lock);//进行加锁操作 if(p->readpos==p->writepos)//判断buff是否为空,为空就等待,直到为非空 { printf("it is empty,wait\n"); pthread_cond_wait(&p->notempty,&p->lock); } val = p->buff[p->readpos]; p->readpos=(p->readpos+1)%BUFF_SIZE; pthread_cond_signal(&p->notfull); pthread_mutex_unlock(&p->lock); return val;}int main(){ Buff_t p=(Buff_t)malloc(sizeof(struct product)); pthread_t product_t,customer_t;//线程id init_func(p); //在使用互斥量、条件变量前,调用初始化函数,进行相关初始化 //创建两个线程,线程producer往buff中每秒存值一次,存30次 //线程customer从buff中每两秒取值一次,并打印,取30次 pthread_create(&product_t, NULL, producer, (void *)p); pthread_create(&customer_t, NULL, customer, (void *)p); //连接线程,等待线程结束 pthread_join(product_t, NULL); pthread_join(customer_t, NULL); //销毁互斥量、条件变量 destory(p); return 0;}
运行结果:
阅读全文
0 0
- linux线程学习(4)
- linux 线程学习(一)
- linux线程学习(1)
- linux线程学习(2)
- linux线程学习(3)
- linux线程学习(5)
- linux线程学习(6)
- Linux线程入门学习(一)-认识线程
- linux学习笔记4--线程编程
- linux学习笔记-线程(1)
- linux 线程学习(二)属性设置
- linux多线程学习(一)---线程基础
- Linux学习(二十一):线程
- linux 线程学习
- linux C 线程学习
- linux线程学习
- Linux线程学习总结
- Linux线程学习笔记
- JVM性能调优
- 动手写一个轮播
- Caffe中计算图像均值的实现(cifar10)
- LIKE模糊查询、使用IN进行范围查询
- STM32堆(stack)和栈(heap)的理解
- linux线程学习(4)
- Spark 加强版WordCount ,统计日志中文件访问数量
- Ubuntu内核编译教程-修改内核(4.5位例)
- 【新闻管理系统】入行以来的第一个项目的感想,送给所有和我一样在磨刀的大学同学们。
- LVS安装配置参考
- 如何遍历map对象
- Swoole入门指南:PHP7安装Swoole详细教程
- 大数据入门:各种大数据技术介绍
- linux刚安装修改root密码