Linux 线程学习之条件变量
互斥锁:用来上锁。
条件变量:用来等待,当条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。通常条件变量和互斥锁同时使用。
函数介绍:
1.
名称: |
pthread_cond_init |
目标: |
条件变量初始化 |
头文件: |
#include < pthread.h> |
函数原形: |
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); |
参数: |
cptr 条件变量 attr 条件变量属性 |
返回值: |
成功返回0,出错返回错误编号。 |
pthread_cond_init函数可以用来初始化一个条件变量。他使用变量attr所指定的属性来初始化一个条件变量,如果参数attr为空,那么它将使用缺省的属性来设置所指定的条件变量。
2.
名称: |
pthread_cond_destroy |
目标: |
条件变量摧毁 |
头文件: |
#include < pthread.h> |
函数原形: |
int pthread_cond_destroy(pthread_cond_t *cond); |
参数: |
cptr 条件变量 |
返回值: |
成功返回0,出错返回错误编号。 |
pthread_cond_destroy函数可以用来摧毁所指定的条件变量,同时将会释放所给它分配的资源。调用该函数的进程也并不要求等待在参数所指定的条件变量上。
3.
名称: |
pthread_cond_wait/pthread_cond_timedwait |
目标: |
条件变量等待 |
头文件: |
#include < pthread.h> |
函数原形: |
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex); int pthread_cond_timedwait(pthread_cond_t *cond,pthread_mutex_t mytex,const struct timespec *abstime); |
参数: |
cond 条件变量 mutex 互斥锁 |
返回值: |
成功返回0,出错返回错误编号。 |
第一个参数*cond是指向一个条件变量的指针。第二个参数*mutex则是对相关的互斥锁的指针。函数pthread_cond_timedwait函数类型与函数pthread_cond_wait,区别在于,如果达到或是超过所引用的参数*abstime,它将结束并返回错误ETIME.pthread_cond_timedwait函数的参数*abstime指向一个timespec结构。该结构如下:
typedef struct timespec{
time_t tv_sec;
long tv_nsex;
}timespec_t;
3.
名称: |
pthread_cond_signal/pthread_cond_broadcast |
目标: |
条件变量通知 |
头文件: |
#include < pthread.h> |
函数原形: |
int pthread_cond_signal(pthread_cond_t *cond); int pthread_cond_broadcast(pthread_cond_t *cond); |
参数: |
cond 条件变量 |
返回值: |
成功返回0,出错返回错误编号。 |
参数*cond是对类型为pthread_cond_t 的一个条件变量的指针。当调用pthread_cond_signal时一个在相同条件变量上阻塞的线程将被解锁。如果同时有多个线程阻塞,则由调度策略确定接收通知的线程。如果调用pthread_cond_broadcast,则将通知阻塞在这个条件变量上的所有线程。一旦被唤醒,线程仍然会要求互斥锁。如果当前没有线程等待通知,则上面两种调用实际上成为一个空操作。如果参数*cond指向非法地址,则返回值EINVAL。
下面是一个简单的例子,我们可以从程序的运行来了解条件变量的作用。
#include <pthread.h> pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*初始化互斥锁*/ void *thread1(void *); int i=1; pthread_create(&t_a,NULL,thread2,(void *)NULL);/*创建线程t_a*/ void *thread1(void *junk) sleep(1); } void *thread2(void *junk) if(i%3!=0) sleep(1); } |
程序创建了2个新线程使他们同步运行,实现进程t_b打印20以内3的倍数,t_a打印其他的数,程序开始线程t_b不满足条件等待,线程t_a运行使a循环加1并打印。直到i为3的倍数时,线程t_a发送信号通知进程t_b,这时t_b满足条件,打印i值。
下面是运行结果:
#cc –lpthread –o cond cond.c
#./cond
thread1:1
thread1:2
thread2:3
thread1:4
thread1:5
thread2:6
thread1:7
thread1:8
thread2:9
备注:
pthread_cond_wait 执行的流程首先将这个mutex解锁, 然后等待条件变量被唤醒, 如果没有被唤醒, 该线程将一直休眠, 也就是说, 该线程将一直阻塞在这个pthread_cond_wait调用中, 而当此线程被唤醒时, 将自动将这个mutex加锁,然后再进行条件变量判断(原因是“惊群效应”,如果是多个线程都在等待这个条件,而同时只能有一个线程进行处理,此时就必须要再次条件判断,以使只有一个线程进入临界区处理。),如果满足,则线程继续执行,最后解锁,
也就是说pthread_cond_wait实际上可以看作是以下几个动作的合体:
解锁线程锁
等待线程唤醒,并且条件为true
加锁线程锁.
pthread_cond_signal仅仅负责唤醒正在阻塞在同一条件变量上的一个线程,如果存在多个线程,系统自动根据调度策略决定唤醒其中的一个线程,在多处理器上,该函数是可能同时唤醒多个线程,同时该函数与锁操作无关,解锁是由pthread_mutex_unlock(&mutex)完成
唤醒丢失问题
在线程并没有阻塞在条件变量上时,调用pthread_cond_signal或pthread_cond_broadcast函数可能会引起唤醒丢失问题。
唤醒丢失往往会在下面的情况下发生:
一个线程调用pthread_cond_signal或pthread_cond_broadcast函数;
另一个线程正处在测试条件变量和调用pthread_cond_wait函数之间;
没有线程正在处在阻塞等待的状态下。
Linux 线程学习之条件变量相关推荐
- Linux线程同步之条件变量
与互斥锁不同,条件变量是用来等待而不是用来上锁的.条件变量用来自动阻塞一个线程,直到某特殊情况发生为止.通常条件变量和互斥锁同时使用. 条件变量使我们可以睡眠等待某种条件出现.条件变量是利用线程间共享 ...
- [转]Linux线程同步之条件变量
与互斥锁不同,条件变量是用来等待而不是用来上锁的.条件变量用来自动阻塞一个线程,直到某特殊情况发生为止.通常条件变量和互斥锁同时使用. 条件变量使我们可以睡眠等待某种条件出现.条件变量是利用线程间共享 ...
- Linux——线程同步(条件变量、POSIX信号量)和线程池
一.线程同步 (一).概念 线程同步是一种多线程关系,指的是线程之间按照特定顺序访问临界资源,进而能够避免线程饥饿问题. 所谓线程饥饿指的是某个线程长期"霸占"临界资源,导致其他线 ...
- linux线程同步(2)-条件变量
一.概述 上一篇,介绍了互斥量.条件变量与互斥量不同,互斥量是防止多线程同时访问共享的互斥变量来保 ...
- linux 条件变量函数,Linux线程同步之条件变量
条件变量变量也是出自POSIX线程标准,另一种线程同步机制,.主要用来等待某个条件的发生.可以用来同步同一进程中的各个线程.当然如果一个条件变量存放在多个进程共享的某个内存区中,那么还可以通过条件变量 ...
- 线程同步之条件变量:pthread_cond_signal和pthread_cond_wait
在多线程编程下,常常出现A线程要等待B线程条件完成后再继续进行,这里等待方式有两种: 1.使用锁+轮询 使用这种方法可以很简单的实现,但是会有一定的性能消耗,其还有一个点要好好把握,就是一次轮询没有结 ...
- 【牛客网C++服务器项目学习】Day8-线程相关、线程锁、条件变量、信号量
项目学习地址:[牛客网C++服务器项目学习] day08 函数:void pthread_exit(void *retval); 功能:终止调用这个函数的线程.如果是一个进程的最后一个线程调用该函数, ...
- C++多线程学习(三)——线程同步之条件变量
前面学习了互斥量似乎我们就可以多线程编程了,多线程也不过如此嘛.然而我们上手coding,用多线程来结局我们实际需求就会发现,似乎多线程也不是很好用.因为我们实际对于多线程的需求,往往线程都是whil ...
- Linux系统编程38:多线程之什么是线程同步以及条件变量函数
文章目录 (1):什么是线程的同步 (2):实现线程同步-条件变量函数 (1):什么是线程的同步 假如有一片临界资源,线程A和B都会修改它,为了保护资源所以要加锁,此时它们之间是互斥的关系.在我们的代 ...
最新文章
- Nginx 学习笔记(六)引入线程池 性能提升9倍
- (四)Thymeleaf标准表达式之——[3-6] 操作符(文本、算术、布尔、比较及相等)...
- SQL server 数据库——T-SQL语句基础
- IP修改器的作用以及用途
- 解决Webview加载不完全导致部分js无效
- django (三) admin后台系统
- LA 3942 Remember the Word
- “弱肉强食,月半者为王” | OpenDILab推出多智能体博弈环境Go-Bigger
- ubantu安装mysql卡住_ubuntu安装mysql遇到的问题
- 单片机与普通微型计算机不同在于,单片机与普通计算机的不同之处在于什么,单片机与普通微型计算机的不同...
- python创建矩阵_Python创建二维数组的正确姿势
- Win7系统下发生一个文件夹,无法删除,解决记录
- 【Vue 组件化开发 三】父组件给子组件传递数据、组件通信(父传子、子传父)、父访问子(children、ref)、动态组件(is、component)
- getAnnotation(Class.class) 为空问题
- Markdown KeTex 德尔塔等于符
- 华为可以更新鸿蒙系统,华为手机如何升级鸿蒙系统 步骤如下
- 软件 ce ee 含义和区别
- spring boot spring data 整合 redis redis keys * 出现 \xac\xed\x00\x05t\x00) 编码异常
- Python打包exe瘦身方法
- 青柠网络验证远程api使用方法
热门文章
- 计算长方形的周长和面积(类和对象)_JAVA
- 【Linux】44.设置ubuntu电脑为简单的密码
- Stanford机器学习笔记-6. 学习模型的评估和选择
- AbstractQueuedSynchronizer 原理分析 - 独占/共享模式
- Java 程序中的多线程
- 虚拟化的发展历程和实现原理——图文详解
- java的mock测试框架
- 浅淡Webservice、WSDL三种服务访问的方式(附案例)
- OpenCV学习笔记(四十一)——再看基础数据结构core OpenCV学习笔记(四十二)——Mat数据操作之普通青年、文艺青年、暴力青年 OpenCV学习笔记(四十三)——存取像素值操作汇总co
- 深度学习(二十五)基于Mutil-Scale CNN的图片语义分割、法向量估计-ICCV 2015