Linux 线程 条件变量
//等待条件
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restric mutex); :把调用线程放到所等待条件的线程列表上
:对传进来已经加过锁的互斥量解锁
:线程进入休眠状态等待被唤醒
注:、2步为原子操作 //通知条件
int pthread_cond_signal(pthread_cond_t *cond); :通知指定条件已经满足
:等待线程重新锁定互斥锁
:等待线程需要重新测试条件是否满足
#include <iostream>
#include <queue>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h> using std::cout;
using std::endl;
using std::queue; #define N 100
#define ST 10 pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t ready = PTHREAD_COND_INITIALIZER; queue<int> que; void* threadProducer(void* arg)
{
while(true)
{
sleep(rand() % ST); cout << "Produce try in...\n";
pthread_mutex_lock(&lock);
cout << "Produce in!\n";
int source = rand() % N;
cout << "Produce " << source << endl;
que.push(source);
pthread_mutex_unlock(&lock);
cout << "Produce out\n"; pthread_cond_signal(&ready);
}
} void* threadConsumer(void* arg)
{
while(true)
{
sleep(rand() % ST); cout << "Consum try in...\n";
pthread_mutex_lock(&lock);
cout << "Consum in!\n";
while(que.empty())
{
pthread_cond_wait(&ready, &lock);
cout << "Consum from sleep\n";
}
cout << "Consum " << que.front() << endl;
que.pop();
pthread_mutex_unlock(&lock);
cout << "Consum out\n\n";
}
} int main(void)
{
pthread_t tProducer, tConsumer;
pthread_create(&tProducer, NULL, threadProducer, NULL);
pthread_create(&tConsumer, NULL, threadConsumer, NULL); pthread_join(tProducer, NULL);
pthread_join(tConsumer, NULL); exit();
}
生消

看到倒数的三四行,消费者进去了,发现没有数据了,则睡眠了,然后生产者进去生产了。
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h> using std::cout;
using std::endl; pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t ready = PTHREAD_COND_INITIALIZER; int data = ; void* threadProducer(void* arg)
{
int i;
for(i = ; i < ; i++)
{
sleep(); if(i % != )
{
cout << "thread1:" << i << endl;
}
else
{
pthread_mutex_lock(&lock);
data = i;
pthread_mutex_unlock(&lock); pthread_cond_signal(&ready);
}
}
} void* threadConsumer(void* arg)
{
while(true)
{
pthread_mutex_lock(&lock);
while(data == ) //no data
pthread_cond_wait(&ready, &lock);
cout <<"thread2:" << data << endl;
if(data == )
break;
else
data = ; //empty data
pthread_mutex_unlock(&lock);
}
} int main(void)
{
pthread_t tProducer, tConsumer;
pthread_create(&tProducer, NULL, threadProducer, NULL);
pthread_create(&tConsumer, NULL, threadConsumer, NULL); pthread_join(tProducer, NULL);
pthread_join(tConsumer, NULL); exit();
}
3打印

程序大致这样:线程1中的循环,如果i不是3的倍数就自己打印了,如果是的话,把这个数放到一个地方(由于这个地方可以被线程2发现,所以要加锁访问),然后唤醒等待数据的线程2(如果线程2还没有在等待,那么这个唤醒则丢失,这是个bug,见下),线程2被唤醒后,消费了这个3的倍数,清空数据区。
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h> using std::cout;
using std::endl; pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t ready = PTHREAD_COND_INITIALIZER; int data = ; void* threadProducer(void* arg)
{
int i;
for(i = ; i < ; i++)
{
sleep(); if(i % != )
{
cout << "thread1:" << i << endl;
}
else
{
pthread_mutex_lock(&lock);
data = i;
pthread_mutex_unlock(&lock); pthread_cond_signal(&ready);
}
}
} void* threadConsumer(void* arg)
{
sleep();
while(true)
{
pthread_mutex_lock(&lock);
while(data == ) //no data
pthread_cond_wait(&ready, &lock);
cout <<"thread2:" << data << endl;
if(data == )
break;
else
data = ; //empty data
pthread_mutex_unlock(&lock);
}
} int main(void)
{
pthread_t tProducer, tConsumer;
pthread_create(&tProducer, NULL, threadProducer, NULL);
pthread_create(&tConsumer, NULL, threadConsumer, NULL); pthread_join(tProducer, NULL);
pthread_join(tConsumer, NULL); exit();
}
bug

//下面是生产者 pthread_mutex_lock(&lock); //加锁访问临界区
/*在这里生产数据*/
pthread_mutex_unlock(&lock); //解锁 pthread_cond_signal(&ready); //通知消费者 //下面是消费者 pthread_mutex_lock(&lock); //加锁访问临界区
while(没有待消费数据)
pthread_cond_wait(&ready, &lock); //睡在这里,等待被唤醒
/*被叫醒了,在这里消费数据*/
pthread_mutex_unlock(&lock); //解锁
Linux 线程 条件变量的更多相关文章
- python线程条件变量Condition(31)
对于线程与线程之间的交互我们在前面的文章已经介绍了 python 互斥锁Lock / python事件Event , 今天继续介绍一种线程交互方式 – 线程条件变量Condition. 一.线程条件变 ...
- Linux Posix线程条件变量
生产者消费者模型 .多个线程操作全局变量n,需要做成临界区(要加锁--线程锁或者信号量) .调用函数pthread_cond_wait(&g_cond,&g_mutex)让这个线程锁在 ...
- Linux 多线程条件变量同步
条件变量是线程同步的另一种方式,实际上,条件变量是信号量的底层实现,这也就意味着,使用条件变量可以拥有更大的自由度,同时也就需要更加小心的进行同步操作.条件变量使用的条件本身是需要使用互斥量进行保护的 ...
- Linux:条件变量
条件变量: 条件变量本身不是锁!但它也可以造成线程阻塞.通常与互斥锁配合使用.给多线程提供一个会合的场所. 主要应用函数: pthread_cond_init函数 pthrea ...
- 笔记3 linux 多线程 条件变量+互斥锁
//cond lock #include<stdio.h> #include<unistd.h> #include<pthread.h> struct test { ...
- Linux Qt使用POSIX多线程条件变量、互斥锁(量)
今天团建,但是文章也要写.酒要喝好,文要写美,方为我辈程序员的全才之路.嘎嘎 之前一直在看POSIX的多线程编程,上个周末结合自己的理解,写了一个基于Qt的用条件变量同步线程的例子.故此来和大家一起分 ...
- linux 互斥锁和条件变量
为什么有条件变量? 请参看一个线程等待某种事件发生 注意:本文是linux c版本的条件变量和互斥锁(mutex),不是C++的. mutex : mutual exclusion(相互排斥) 1,互 ...
- Linux 线程管理
解析1 LINUX环境下多线程编程肯定会遇到需要条件变量的情况,此时必然要使用pthread_cond_wait()函数.但这个函数的执行过程比较难于理解. pthread_cond_wait()的工 ...
- c++ 条件变量
.条件变量创建 静态创建:pthread_cond_t cond=PTHREAD_COND_INITIALIZER; 动态创建:pthread_cond _t cond; pthread_cond_i ...
随机推荐
- C++中String类的实现
原文:http://noalgo.info/382.html String是C++中的重要类型,程序员在C++面试中经常会遇到关于String的细节问题,甚至要求当场实现这个类.只是由于时间关系,可能 ...
- shell 学习笔记
<Linux命令行与shell脚本编程大全>笔记 wkss 其他:http://www.cnblogs.com/pengdonglin137/p/3528303.html 一.基本命令 ...
- python编码encode和decode
计算机里面,编码方法有很多种,英文的一般用ascii,而中文有unicode,utf-8,gbk,utf-16等等. unicode是 utf-8,gbk,utf-16这些的父编码,这些子编码都能转换 ...
- Tfs服务器迁移(更改IP)后客户端(vs2013)配置方法
一.前言 公司开发项目需要进驻客户现场,局域网中的tfs代码服务器有时会有修改ip的情况发生.服务器ip修改后在vs2013中更改服务器ip地址非常麻烦,有些时候需要将代码重新进行映射.多次试验后将可 ...
- Java SE ---流程控制语句
java的控制流程有三种: 一,顺序流程 自上而下,按照代码的先后顺序执行 二,分支流程 1,if/else语句 2,swit ...
- 数据结构【三】:简单优先队列PriorityQueue
在数据结构[二]:简单阻塞队列BlockingQueue的基础上添加权限属性:priority,并控制enqueue时根据priority排序插入. 1.定义priority取值范围0~9 2.deq ...
- 重构13-Extract Method Object(提取方法对象)
重构来自于Martin Fowler的重构目录.你可以在这里找到包含简介的原始文章. 在我看来,这是一个比较罕见的重构,但有时却终能派上用场.当你尝试进行提取方法的重构时,需要引入大量的方法.在一个 ...
- SQL Server 2008数据类型
在创建表时,必须为表中的每列指派一种数据类型. 今天在研究二进制存储图片时候竟然不知道image类型就是二进制类型?!所有就搜集了sql中的各种数据类型汇总,成功在于点滴积累. 1. 字符数据类型 数 ...
- JavaScript 中的算术运算
JavaScript中算术运算在溢出(overflow).下溢(underflow)或被零整除时不会报错,当数字运算结果超过了JavaScript所能表示的数字上限(溢出),结果为一个特殊的无穷大(i ...
- VMware系统运维(十四)部署虚拟化桌面 Horzion View Manager 5.2 配置许可
1.通过网页访问https://conntionserver.testad.local/admin,打开如下图所示页面:输入用户名密码 2.进来以后配置View 许可,点击"编辑许可证&qu ...