互斥锁是用来给资源上锁的,而条件变量是用来等待而不是用来上锁的。

条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。

通常条件变量和互斥锁同时使用。

和条件变量使用有关的几个重要函数:

int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr);
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex *mutex,const timespec *abstime);
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond); //解除所有线程的阻塞

1. 初始化:

条件变量采用的数据类型是pthread_cond_t, 在使用之前必须要进行初始化, 这包括两种方式:

  • 静态: 可以把常量PTHREAD_COND_INITIALIZER给静态分配的条件变量.
  • 动态: pthread_cond_init函数, 是释放动态条件变量的内存空间之前, 要用pthread_cond_destroy对其进行清理.

#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);

成功则返回0, 出错则返回错误编号.

当pthread_cond_init的attr参数为NULL时, 会创建一个默认属性的条件变量; 非默认情况以后讨论.

2. 等待条件:

#include <pthread.h>

int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restric mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict timeout);

成功则返回0, 出错则返回错误编号.

这两个函数分别是阻塞等待和超时等待.

等待条件函数等待条件变为真, 传递给pthread_cond_wait的互斥量对条件进行保护, 调用者把锁住的互斥量传递给函数. 函数把调用线程放到等待条件的线程列表上, 然后对互斥量解锁, 这两个操作是原子的. 这样便关闭了条件检查和线程进入休眠状态等待条件改变这两个操作之间的时间通道, 这样线程就不会错过条件的任何变化.

当pthread_cond_wait返回时, 互斥量再次被锁住.

3. 通知条件:

#include <pthread.h>

int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);

成功则返回0, 出错则返回错误编号.

这两个函数用于通知线程条件已经满足. 调用这两个函数, 也称向线程或条件发送信号. 必须注意, 一定要在改变条件状态以后再给线程发送信号.

条件变量使用示例

下面是个非常简单的例子,很好的演示了条件变量如何使用。

我将创建一个生产者线程,两个消费者线程,通过互斥量和条件变量同步他们的生产和消费操作。

需要注意的一个地方是,pthread_cond_wait操作必须传入一个条件变量和互斥量,线程先对互斥量上锁,然后再执行pthread_cond_wait,pthread_cond_wait会将互斥量解锁。

pthread_cond_wait在while循环中而不在if中的原因是,“可能被意外唤醒”,所以需要在唤醒之后再检查缓冲区。

 #include <stdio.h>
#include <pthread.h>
#include <unistd.h> pthread_cond_t condc,condp;
pthread_mutex_t the_mutex; unsigned int buffer = ;
const int MAX = ; void *producer(void *ptr){
for(int i = ; i < MAX; i++){
pthread_mutex_lock(&the_mutex);
while(buffer != ) pthread_cond_wait(&condp, &the_mutex);
sleep();
buffer = i;
printf("producer pthread produce one production %d.\n", i);
pthread_cond_broadcast(&condc);//唤醒两个消费者线程
pthread_mutex_unlock(&the_mutex);
}
pthread_exit();
} void *consumer1(void *ptr){
for(int i = ; i < MAX; i++){
pthread_mutex_lock(&the_mutex);
while(buffer == ) pthread_cond_wait(&condc, &the_mutex);
printf("consumer1 pthread consume one production %d.\n", buffer);
buffer = ;
pthread_cond_signal(&condp);
pthread_mutex_unlock(&the_mutex);
}
pthread_exit();
}
void *consumer2(void *ptr){
for(int i = ; i < MAX; i++){
pthread_mutex_lock(&the_mutex);
while(buffer == ) pthread_cond_wait(&condc, &the_mutex);
printf("consumer2 pthread consume one production %d.\n", buffer);
buffer = ;
pthread_cond_signal(&condp);
pthread_mutex_unlock(&the_mutex);
}
pthread_exit();
} int main(void){
pthread_t pro, con1, con2;
pthread_mutex_init(&the_mutex,);
pthread_cond_init(&condc,);
pthread_cond_init(&condp,);
pthread_create(&con1, , consumer1, );
pthread_create(&pro, , producer, );
pthread_create(&con2, , consumer2, );
pthread_join(pro, );
pthread_join(con1, );
pthread_join(con2, );
pthread_cond_destroy(&condc);
pthread_cond_destroy(&condp);
pthread_mutex_destroy(&the_mutex);
return ;
}

运行结果

Linux线程同步——条件变量的更多相关文章

  1. linux Posix线程同步(条件变量) 实例

    条件变量:与互斥量一起使用,暂时申请不到某资源时进入条件阻塞等待,当资源具备时线程恢复运行 应用场合:生产线程不断的生产资源,并通知产生资源的条件,消费线程在没有资源情况下进入条件等待,一直等到条件信 ...

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

    条件变量(Condition Variables) 参考资料:http://game-lab.org/posts/posix-thread-cn/#5.1 条件变量是什么? 条件变量为我们提供了另一种 ...

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

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

  4. 【转】 Linux 线程同步的三种方法

    线程的最大特点是资源的共享性,但资源共享中的同步问题是多线程编程的难点.linux下提供了多种方式来处理线程同步,最常用的是互斥锁.条件变量和信号量. 一.互斥锁(mutex) 通过锁机制实现线程间的 ...

  5. Java线程:条件变量、原子量、线程池等

    一.条件变量 条件变量实现了java.util.concurrent.locks.Condition接口,条件变量的实例化就是通过一个Lock对象上调用newCondition()方法获得的,这样条件 ...

  6. linux 线程同步(二)

    信号量 信号量是相互排斥锁的升级版把相互排斥锁中1变成了n.举个简单的样例:如果如今有10个人,有一部手机.这10个人都竞争来使用手机打电话这就是相互排斥锁.对于信号量,如今可能是有4部手机,这10个 ...

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

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

  8. Linux 线程同步的三种方法(互斥锁、条件变量、信号量)

    互斥锁 #include <cstdio> #include <cstdlib> #include <unistd.h> #include <pthread. ...

  9. linux多线程-互斥&条件变量与同步

    多线程代码问题描述 我们都知道,进程是操作系统对运行程序资源分配的基本单位,而线程是程序逻辑,调用的基本单位.在多线程的程序中,多个线程共享临界区资源,那么就会有问题: 比如 #include < ...

随机推荐

  1. H - The LCIS on the Tree HDU - 4718

    The LCIS on the Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Oth ...

  2. Qt使用gtest进行C++单元测试-01

    环境: win7/win10+qt5.8.0(MinGW), 1.gtest获取: 从:https://www.bogotobogo.com/cplusplus/google_unit_test_gt ...

  3. (2)Oracle基础--表空间

    · 表空间概述 <1> 理解表空间 ① 表空间与数据库的关系: 表空间是数据库的逻辑存储空间,可以理解为在数据库中开辟的一块空间,用于存放数据库的对象. 一个数据库可以由多个表空间构成.O ...

  4. php文件每隔几秒执行一次

    说实话,linux 下面的crontab 任务完全可以实现所有的定时任务脚本,但是有些脚本只需要在一段时间内执行,过了这段时间之后,就不再执行定时脚本了.在使用crontab的时候,就需要人为的关闭掉 ...

  5. webpack快速入门——处理HTML中的图片

    在webpack中是不喜欢你使用标签<img>来引入图片的,但是我们作前端的人特别热衷于这种写法, 国人也为此开发了一个:html-withimg-loader.他可以很好的处理我们在ht ...

  6. 大数据技术之_19_Spark学习_01_Spark 基础解析小结(无图片)

    1.准备安装包 2.Spark Standalone 即独立模式  2.1.解压安装包到你安装的目录.  2.2.拷贝 conf 目录下的 slaves 文件,将 slave 节点的 hostname ...

  7. HTML+Javascript制作拼图小游戏详解(二)

    上一篇我们说了网页的基本布局.接下来将为大家带来具体的实现方法. 拼图通表格来实现,做一个方形的表格,改变其大小使之如图所示. 试想一下如果我们将一张图片剪成6张分别放入对应位置,然后再把它打乱,这样 ...

  8. D09——C语言基础学PYTHON

    C语言基础学习PYTHON——基础学习D09 20180903内容纲要: 线程.进程 1.paramiko 2.线程.进程初识 3.多线程 (1)线程的调用方式 (2)join (3)线程锁.递归锁. ...

  9. WebDriverAPI(6)

    在指定元素上方进行鼠标悬浮 测试网址 http://www.baidu.com Java语言版本实例 @Test public void roverOnElement() { driver.manag ...

  10. POJ 1183

    #include<iostream> #include<stdio.h> using namespace std; int main() { //freopen("a ...