41.1 概念

41.1.1 条件变量的介绍

  • 互斥锁的缺点是它只有两种状态:锁定和非锁定
  • 条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足
  • 条件变量内部是一个等待队列,放置等待的线程,线程在条件变量上等待和通知,互斥锁用来保护等待队列(对等待队列上锁),条件变量通常和互斥锁一起使用
  • 条件变量允许线程等待特定条件发生,当条件不满足时,线程通常先进入阻塞状态,等待条件发生变化。一旦其它的某个线程改变了条件,可唤醒一个或多个阻塞的线程
  • 具体的判断条件还需用户给出
  • 条件变量数据类型: pthread_cond_t

41.1.2 条件变量创建和销毁

 #include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond, pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);
  • 函数参数:

    • cond:条件变量
    • attr:条件变量属性
  • 返回值:
    • 成功,返回 0;出错,返回错误编号

41.1.3 条件变量等待操作

 #include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
int pthread_cond_timewait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict timeout); struct timespec {
time_t tv_sec; /** seconds */
ong tv_nsec; /** nanoseconds */
};
  • 函数参数:

    • cond:条件变量
    • mutex:互斥锁
  • 返回值:成功,返回 0,出错,返回错误编号
  • 互斥锁 mutex 是对条件变量 cond 的保护
  • 线程由于调用 wait 函数阻塞,否则释放互斥锁

41.1.4 条件变量通知操作

 #include <pthread.h>
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
  • 函数参数:

    • cond:条件变量
  • 返回值:成功,返回 0;失败,返回错误编号
  • 当条件满足,线程需要通知等待的线程
  • pthread_cond_signal 函数通知单个线程
  • pthread_cond_broadcast 函数通知所有线程

41.1.5 pthread_cond_wait(cond, mutex) 函数内部流程

  1. unlock(&mutex):释放锁
  2. lock(&mutex)
  3. 将线程自己插入到条件变量的等待队列中
  4. unlock(&mutex);
  5. 当前等待的线程阻塞 <<== 等待其他线程通知唤醒(signal 或 broadcast)
  6. 在唤醒后,lock(&mutex)
  7. 从等待队列中删除线程自己

41.2 例子

  一个线程负责计算结果,一个线程负责获取结果

 #include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h> /** 两个线程定义的共享资源 */
typedef struct {
int res;
int is_wait; ///< 用户给出的用于判断的条件
pthread_cond_t cond; ///< 条件变量
pthread_mutex_t mutex; ///< 互斥锁
}Result; /** 计算并将结果放置在 Result 中的线程运行函数 */
void *set_fn(void *arg)
{
Result *r = (Result *)arg;
int i = ;
int sum = ; for(; i <= ; i++){
sum += i;
} /** 将结果放置到 Result 中 */
r->res = sum; pthread_mutex_lock(&r->mutex);
/** 判断获取结果的线程是否准备好 */
while(!r->is_wait){
pthread_mutex_unlock(&r->mutex);
usleep();
pthread_mutex_lock(&r->mutex);
}
pthread_mutex_unlock(&r->mutex); /** 通知唤醒等待的那个获取结果的线程 */
pthread_cond_broadcast(&r->cond); return (void *);
} /** 获得结果的线程运行函数 */
void *get_fn(void *arg)
{
Result *r = (Result *)arg; /** 对两个线程共享的判断条件进行保护(加锁) */
/** 两个线程对判断条件的操作是互斥的 */
pthread_mutex_lock(&r->mutex);
/** 当线程启动后,将此变量设置为1,代表此线程已经准备好了 */
r->is_wait = ; /** 获取结果的线程等待 */
pthread_cond_wait(&r->cond, &r->mutex); /** 被唤醒后 */
pthread_mutex_unlock(&r->mutex); /** 去获取计算结果 */
int res = r->res;
printf("0x%lx get sum is %d\n", pthread_self(), res); return (void *);
} int main(void)
{
int err;
pthread_t cal, get; Result r;
r.is_wait = ;
pthread_cond_init(&r.cond, NULL);
pthread_mutex_init(&r.mutex, NULL); /** 启动获取结果的线程 */
if((err = pthread_create(&get, NULL, get_fn, (void *)&r)) != ){
perror("pthread create error");
} /** 启动计算结果的线程 */
if((err = pthread_create(&cal, NULL, set_fn, (void *)&r)) != ){
perror("pthread create error");
} pthread_join(cal, NULL);
pthread_join(get, NULL); pthread_cond_destroy(&r.cond);
pthread_mutex_destroy(&r.mutex); pthread_cond_destroy(&r.cond);
pthread_mutex_destroy(&r.mutex);
return ;
}

  编译执行结果:

  

四十一、Linux 线程——线程同步之条件变量的更多相关文章

  1. Linux线程同步:条件变量

    条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用.使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化.一旦其它 ...

  2. linux线程同步(2)-条件变量

    一.概述                                                    上一篇,介绍了互斥量.条件变量与互斥量不同,互斥量是防止多线程同时访问共享的互斥变量来保 ...

  3. 线程同步,条件变量pthread_cond_wait

    与互斥锁不同,条件变量是用来等待而不是用来上锁的.条件变量用来自动阻塞一个线程,直到某特殊情况发生为止.条件变量使我们可以睡眠等待某种条件出现.条件变量是利用线程间共享的全局变量进行同步的一种机制,主 ...

  4. C++11 中的线程、锁和条件变量

    转自:http://blog.jobbole.com/44409/ 线程 类std::thread代表一个可执行线程,使用时必须包含头文件<thread>.std::thread可以和普通 ...

  5. 【转】【C++】C++ 中的线程、锁和条件变量

    线程 类std::thread代表一个可执行线程,使用时必须包含头文件<thread>.std::thread可以和普通函数,匿名函数和仿函数(一个实现了operator()函数的类)一同 ...

  6. (转)Java线程:新特征-条件变量

    Java线程:新特征-条件变量   条件变量是Java5线程中很重要的一个概念,顾名思义,条件变量就是表示条件的一种变量.但是必须说明,这里的条件是没有实际含义的,仅仅是个标记而已,并且条件的含义往往 ...

  7. Linux多线程编程详细解析----条件变量 pthread_cond_t

    Linux操作系统下的多线程编程详细解析----条件变量 1.初始化条件变量pthread_cond_init #include <pthread.h> int pthread_cond_ ...

  8. Linux多线程实践(8) --Posix条件变量解决生产者消费者问题

    Posix条件变量 int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr); int pthread_co ...

  9. linux C++ 多线程使用pthread_cond 条件变量

    1. 背景 多线程中经常需要使用到锁(pthread_mutex_t)来完成多个线程之间的互斥操作. 但是互斥锁有一个明显到缺点: 只有两种状态,锁定和非锁定. 而条件变量则通过允许线程阻塞并等待另一 ...

随机推荐

  1. [TJOI2015]线性代数(最小割)

    题目描述 给出一个N*N的矩阵B和一个1*N的矩阵C.求出一个1*N的01矩阵A.使得 D=(A*B-C)*A^T最大.其中A^T为A的转置.输出D 题解 观察上面那个式子发现,当一个bij有贡献时当 ...

  2. [NOI2015]寿司晚宴(状压dp)

    为了庆祝NOI的成功开幕,主办方为大家准备了一场寿司晚宴.小G和小W作为参加NOI的选手,也被邀请参加了寿司晚宴. 在晚宴上,主办方为大家提供了n−1种不同的寿司,编号1,2,3,⋯,n-1,其中第种 ...

  3. Linux里文件和文件夹权限的含义

      文件的权限: r : 可以读取此文件的实际内容. w: 可以编辑.新增或者是修改该文件的内容(但不含删除该文件),如果没有r权限,无法w. x : 该文件具有被系统执行的权限,可以删除. 文件夹的 ...

  4. Python3 与 C# 扩展之~基础拓展

      上次知识回顾:https://www.cnblogs.com/dotnetcrazy/p/9278573.html 代码裤子:https://github.com/lotapp/BaseCode ...

  5. 编写高质量代码:改善Java程序的151个建议 --[52~64]

    编写高质量代码:改善Java程序的151个建议 --[52~64] 推荐使用String直接量赋值 Java为了避免在一个系统中大量产生String对象(为什么会大量产生,因为String字符串是程序 ...

  6. bzoj4842 Delight for a Cat

    题意:n天内你每天可以s或者e,分别有一定的收益. 每连续k天中s的天数要大于ds,e的天数要大于de,求最大收益. 解:费用流解线性规划. 先假设全部选e,然后一天s的收益为si - ei ai表示 ...

  7. T4模版 mysql

    MysqlDbhelper.ttinclude <#@ assembly name="System.Core"#> <#@ assembly name=" ...

  8. Map.putAll方法——追加另一个Map对象到当前Map集合

    转: Map.putAll方法——追加另一个Map对象到当前Map集合(转) 该方法用来追加另一个Map对象到当前Map集合对象,它会把另一个Map集合对象中的所有内容添加到当前Map集合对象. 语法 ...

  9. eclipse添加market ,maven

    添加market 转载自http://blog.csdn.net/buptdavid/article/details/42423247 Eclipse Marketplace是个插件应用商店,很实用的 ...

  10. Failed to start Vsftpd ftp daemon错误

    配置 vsftpd.conf文件后 重启ftp服务出现 Failed to start Vsftpd ftp daemon错误 总是 启动失败 解决方法 将配置文件中的 listen=YES 改为 l ...