42.1 线程状态转换
42.1.1 状态转换图
42.1.2 一个线程计算,多个线程获取的案例
#include
#include
#include
#include
/** 两个线程定义的共享资源 */
typedef struct {
int res;
int counter; ///< 用于统计获取结果线程的数量
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->counter < ){
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->counter++;
/** 获取结果的线程等待 */
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, get1, get2;
Result r;
r.counter = ;
pthread_cond_init(&r.cond, NULL);
pthread_mutex_init(&r.mutex, NULL);
/** 启动获取结果的线程 */
if((err = pthread_create(&get1, NULL, get_fn, (void *)&r)) != ){
perror("pthread create error");
}
if((err = pthread_create(&get2, 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(get1, NULL);
pthread_join(get2, NULL);
pthread_cond_destroy(&r.cond);
pthread_mutex_destroy(&r.mutex);
pthread_cond_destroy(&r.cond);
pthread_mutex_destroy(&r.mutex);
return ;
}
编译运行结果如下:
42.2 读者-写者案例
几种情况:
1 个写者,1 个读者
1 个写者,多个读者
多个写者,多个读者
完成第一种情况:
#include
#include
#include
#include
#include
typedef struct {
int value;
/** 读者 */
pthread_cond_t rc;
pthread_mutex_t rm;
int r_wait;
/** 写者 */
pthread_cond_t wc;
pthread_mutex_t wm;
int w_wait;
}Storage;
/** 写入数据的函数 */
void set_data(Storage *s, int value)
{
s->value = value;
}
/** 获取数据的函数 */
int get_data(Storage *s)
{
return s->value;
}
/** 写者线程运行函数定义 */
void *set_th(void *arg)
{
Storage *s = (Storage *)arg;
int i = ;
for(; i <= ; i++){
/** 写入数据 */
set_data(s, i +);
printf("0x%lx(%-5d) write data : %d\n", pthread_self(), i, i + );
pthread_mutex_lock(&s->rm);
/** 判断读者线程是否准备好 */
while(!s->r_wait){
pthread_mutex_unlock(&s->rm);
sleep();
pthread_mutex_lock(&s->rm);
}
s->r_wait = ;
pthread_mutex_unlock(&s->rm);
/** 通知读者线程读取数据 */
pthread_cond_broadcast(&s->rc);
/** 写者线程自阻塞等待读者线程通知已经读取完毕,
* 然后唤醒写者线程继续写入数据 */
pthread_mutex_lock(&s->wm);
s->w_wait = ;
pthread_cond_wait(&s->wc, &s->wm);
pthread_mutex_unlock(&s->wm);
}
return (void *);
}
/** 读者线程运行函数定义 */
void *get_th(void *arg)
{
Storage *s = (Storage *)arg;
int i = ;
for(; i <= ; i++){
pthread_mutex_lock(&s->rm);
s->r_wait = ;
pthread_cond_wait(&s->rc, &s->rm);
pthread_mutex_unlock(&s->rm);
/** 读者线程被唤醒后读取数据 */
int value = get_data(s);
printf("0x%lx(%-5d) read data: %d\n", pthread_self(), i, value);
pthread_mutex_lock(&s->wm);
/** 判断写者线程是否准备好 */
while(!s->w_wait){
pthread_mutex_unlock(&s->wm);
sleep();
pthread_mutex_lock(&s->wm);
}
/** 唤醒写者线程 */
s->w_wait = ;
pthread_mutex_unlock(&s->wm);
pthread_cond_broadcast(&s->wc);
}
return (void *);
}
int main(void)
{
int err;
pthread_t rth, wth;
Storage s;
s.r_wait = ;
s.w_wait = ;
pthread_mutex_init(&s.rm, NULL);
pthread_mutex_init(&s.wm, NULL);
pthread_cond_init(&s.rc, NULL);
pthread_cond_init(&s.wc, NULL);
/** 创建一个读者线程和写者线程 */
if((err = pthread_create(&rth, NULL, get_th, (void *)&s)) != ){
perror("pthread create error");
}
if((err = pthread_create(&wth, NULL, set_th, (void *)&s)) != ){
perror("pthread create error");
}
pthread_join(rth, NULL);
pthread_join(wth, NULL);
pthread_mutex_destroy(&s.rm);
pthread_mutex_destroy(&s.wm);
pthread_cond_destroy(&s.rc);
pthread_cond_destroy(&s.wc);
return ;
}
四十一、Linux 线程——线程同步之条件变量
41.1 概念 41.1.1 条件变量的介绍 互斥锁的缺点是它只有两种状态:锁定和非锁定 条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足 条件变量内部是一个等待队列,放置等待 ...
linux线程同步(2)-条件变量
一.概述 上一篇,介绍了互斥量.条件变量与互斥量不同,互斥量是防止多线程同时访问共享的互斥变量来保 ...
Linux线程同步:条件变量
条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用.使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化.一旦其它 ...
Gradle 1.12用户指南翻译——第四十二章. Announce插件
本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...
linux 条件变量与线程池
条件变量Condition Variables 概述 1. 条件变量提供了另外一种线程同步的方式.如果没有条件变量,程序需要使用线程连续轮询(可能在临界区critical section内)方式检查条 ...
线程同步,条件变量pthread_cond_wait
与互斥锁不同,条件变量是用来等待而不是用来上锁的.条件变量用来自动阻塞一个线程,直到某特殊情况发生为止.条件变量使我们可以睡眠等待某种条件出现.条件变量是利用线程间共享的全局变量进行同步的一种机制,主 ...
“全栈2019”Java第四十二章:静态代码块与初始化顺序
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
NeHe OpenGL教程 第四十二课:多重视口
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
网站开发进阶(四十二)巧用clear:both
网站开发进阶(四十二)巧用clear:both 前言 我们在制作网页中用div+css或者称xhtml+css都会遇到一些很诡异的情况,明明布局正确,但是整个画面却混乱起来了,有时候在IE6下看的很正 ...
随机推荐
iOS组件化思路 <;转>;
随着应用需求逐步迭代,应用的代码体积将会越来越大,为了更好的管理应用工程,我们开始借助CocoaPods版本管理工具对原有应用工程进行拆分.但是仅仅完成代码拆分还不足以解决业务之间的代码耦合,为了更好 ...
Linux下jvm、tomcat、mysql、log4j优化配置笔记
小菜一直对操作系统心存畏惧,以前也很少接触,这次创业购买了Linux云主机,由于木有人帮忙,只能自己动手优化服务器了.... 小菜的云主机配置大致为:centeos6(32位),4核心cpu,4G内存 ...
android resources使用总结
http://developer.android.com/guide/topics/resources/more-resources.html http://developer.android.com ...
【HTML/XML 10】XML文档中的Schema文件
导读:DTD是对XML文档进行有效性验证的方法之一,事实上,继DTD之后,出现了用来规范和描述XML文档的第二代标准:Schema.Schema是DTD的继承,但是也有其不同的地方,它是真正的以独立的 ...
centos6 下用yum 安装 nginx
以下操作在Cento6.4 系统下实现 一.更新使用163的库 vi /etc/yum.repos.d/CentOS-Base.repo yum update [base] name=CentOS-$ ...
Objective-c 中的变量
OC中的语言变量,按作用域可分为两种:局部变量和全局变量. 局部变量:也称为内部变量,局部变量是在方法内部声明的.其作用域仅限于方法内,离开该方法再使用这个变量就是非法的. 全局变量:也称为外部变量, ...
到底什么样的企业才适合实施SAP系统?
SAP系统作为全宇宙第一的ERP,号称世界500强里面有80%的企业部署了SAP系统,总部位于德国沃尔多夫市,在全球拥有6万多名员工,遍布全球130个国家,并拥有覆盖全球11,500家企业的合作伙伴网 ...
Jquery第一篇【介绍Jquery、回顾JavaScript代码、JS对象与JQ对象的区别】
什么是Jquery? Jquey就是一款跨主流浏览器的JavaScript库,简化JavaScript对HTML操作 就是封装了JavaScript,能够简化我们写代码的一个JavaScript库 为 ...
Oracle数据库基础练习题
--1.查询和SMITH相同部门的员工姓名和雇用日期select ename,hiredate from emp where deptno=(select deptno from emp where ...