当前位置: 首页 > news >正文

徐州手机模板建站微信加精准客源软件

徐州手机模板建站,微信加精准客源软件,免费制作网站和网页,如何成立公司〇、前言 本文是对《OSTEP》第三十章的实践与总结。 一、条件变量 #include <pthread.h> #include <stdio.h> #include <assert.h>int buffer; int count 0; // 资源为空// 生产,在 buffer 中放入一个值 void put(int value) {assert(count 0);count 1…

〇、前言

本文是对《OSTEP》第三十章的实践与总结。

一、条件变量

#include <pthread.h>
#include <stdio.h>
#include <assert.h>int buffer;
int count = 0; // 资源为空// 生产,在 buffer 中放入一个值
void put(int value) {assert(count == 0);count = 1;buffer = value;
}
// 消费,取出 buffer 中的值
int get() {assert(count == 1);count = 0;return buffer;
}/***********第一版本**********/
// 生产者
void *producer(void *arg) {int loops = *((int *)arg);for (int i = 0; i < loops; i++) {put(i);}return NULL;
}
// 消费者
void *consumer(void *arg) {while (1) {int temp = get();printf("消费的值:%d\n", temp);}return NULL;
}int main() {pthread_t p1, p2;int arg = 100;pthread_create(&p1, NULL, producer, &arg);pthread_create(&p2, NULL, consumer, NULL);// 等待两个线程结束pthread_join(p1, NULL);pthread_join(p2, NULL);return 0;
}

运行:

*** chap30_条件变量 % gcc -o a con_prodece.c
*** chap30_条件变量 % ./a
Assertion failed: (count == 0), function put, file con_prodece.c, line 10.
消费的值:0
Assertion failed: (count == 1), function get, file con_prodece.c, line 16.
zsh: abort      ./a

可以看到,断言直接失败。

pthread_cond_t cond;
pthread_mutex_t mutex;
/***********第二版本**********/
// 生产者
void *producer(void *arg) {int loops = *((int *)arg);for (int i = 0; i < loops; i++) {pthread_mutex_lock(&mutex);if (count == 1) {pthread_cond_wait(&cond, &mutex);}put(i);pthread_mutex_unlock(&mutex);pthread_cond_signal(&cond);}return NULL;
}
// 消费者
void *consumer(void *arg) {int loops = *((int *)arg);for (int i = 0; i < loops; i++) {pthread_mutex_lock(&mutex);if (count == 0) {pthread_cond_wait(&cond, &mutex);}int temp = get();pthread_mutex_unlock(&mutex);printf("消费:%d\n", temp);pthread_cond_signal(&cond); }return NULL;
}int main() {// 初始化互斥锁和条件变量pthread_mutex_init(&mutex, NULL);pthread_cond_init(&cond, NULL);pthread_t p1, p2;int arg = 100;pthread_create(&p1, NULL, producer, &arg);pthread_create(&p2, NULL, consumer, &arg);// 等待两个线程结束pthread_join(p1, NULL);pthread_join(p2, NULL);// 销毁互斥锁和条件变量pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);return 0;
}

运行结果:

*** chap30_条件变量 % ./a                    
消费:0
消费:1
消费:2
消费:3
...
消费:95
消费:96
消费:97
消费:98
消费:99

可以看到,在两个线程的情况下,工作的很好。

/***********第三版本**********/
// 生产者
void *producer(void *arg) {int loops = *((int *)arg);for (int i = 0; i < loops; i++) {pthread_mutex_lock(&mutex);if (count == 1) {pthread_cond_wait(&cond, &mutex);}put(i);pthread_mutex_unlock(&mutex);pthread_cond_signal(&cond);}return NULL;
}
// 消费者
void *consumer(void *arg) {int loops = *((int *)arg);for (int i = 0; i < loops; i++) {pthread_mutex_lock(&mutex);if (count == 0) {pthread_cond_wait(&cond, &mutex);}int temp = get();pthread_mutex_unlock(&mutex);printf("消费:%d\n", temp);pthread_cond_signal(&cond); }return NULL;
}int main() {// 初始化互斥锁和条件变量pthread_mutex_init(&mutex, NULL);pthread_cond_init(&cond, NULL);pthread_t p1, p2, p3;int arg = 100;int arg1 = 50;int arg2 = 50;pthread_create(&p1, NULL, producer, &arg);pthread_create(&p2, NULL, consumer, &arg1);pthread_create(&p3, NULL, consumer, &arg2);// 等待两个线程结束pthread_join(p1, NULL);pthread_join(p2, NULL);pthread_join(p3, NULL);// 销毁互斥锁和条件变量pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);return 0;
}

运行结果:

*** chap30_条件变量 % gcc -o a con_prodece2.c
*** chap30_条件变量 % ./a                    
消费:0
消费:1
Assertion failed: (count == 1), function get, file con_prodece2.c, line 18.
zsh: abort      ./a

可以看到,再增加了一个消费线程之后,出现了断言错误。这是因为出现了假唤醒,使得某个线程醒来后,断言错误。解决方法很简单,直接将 if()换成 while():

/***********第三版本**********/
// 解决虚假唤醒
// 生产者
void *producer(void *arg) {int loops = *((int *)arg);for (int i = 0; i < loops; i++) {pthread_mutex_lock(&mutex);while (count == 1) {pthread_cond_wait(&cond, &mutex);}put(i);pthread_mutex_unlock(&mutex);pthread_cond_signal(&cond);}return NULL;
}
// 消费者
void *consumer(void *arg) {int loops = *((int *)arg);for (int i = 0; i < loops; i++) {pthread_mutex_lock(&mutex);while (count == 0) {pthread_cond_wait(&cond, &mutex);}int temp = get();pthread_mutex_unlock(&mutex);printf("消费:%d\n", temp);pthread_cond_signal(&cond); // 在解锁之后发出信号}return NULL;
}int main() {// 初始化互斥锁和条件变量pthread_mutex_init(&mutex, NULL);pthread_cond_init(&cond, NULL);pthread_t p1, p2, p3;int arg = 100;int arg1 = 50;int arg2 = 50;pthread_create(&p1, NULL, producer, &arg);pthread_create(&p2, NULL, consumer, &arg1);pthread_create(&p3, NULL, consumer, &arg2);// 等待两个线程结束pthread_join(p1, NULL);pthread_join(p2, NULL);pthread_join(p3, NULL);// 销毁互斥锁和条件变量pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);return 0;
}

运行结果:

luliang@shenjian chap30_条件变量 % ./a
消费:0
消费:2
消费:1
消费:3
消费:4
消费:5
...

可以看到会卡住,这其实是由于三个线程都睡眠导致的,这种情况是怎么发生的呢?
假设生产者唤醒了第一个消费者,消费者又恰巧唤醒了第二个生产者,第二个生产者被唤醒之后又睡眠。这样三个线程都在睡眠。解决问题的办法就是消费者只能唤醒生产者,生产者只能唤醒消费者。以下就是终极版本的代码:

#include <assert.h>
#include <pthread.h>
#include <stdio.h>int buffer;
int count = 0; // 资源为空
pthread_cond_t cond_consumer;
pthread_cond_t cond_procedure;
pthread_mutex_t mutex;// 生产,在 buffer 中放入一个值
void put(int value) {assert(count == 0);count = 1;buffer = value;
}
// 消费,取出 buffer 中的值
int get() {assert(count == 1);count = 0;return buffer;
}/***********第四版本**********/
// 假设生产者唤醒了第一个消费者,消费者又唤醒了第二个生产者,第二个生产者
// 之后又睡眠.这样三个线程都在睡眠.
// 核心问题就是,消费者只能唤醒生产者,生产者只能唤醒消费者.
// 生产者
void *producer(void *arg) {int loops = *((int *)arg);for (int i = 0; i < loops; i++) {pthread_mutex_lock(&mutex);while (count == 1) {pthread_cond_wait(&cond_procedure, &mutex);}put(i);pthread_mutex_unlock(&mutex);pthread_cond_signal(&cond_consumer);}return NULL;
}
// 消费者
void *consumer(void *arg) {int loops = *((int *)arg);for (int i = 0; i < loops; i++) {pthread_mutex_lock(&mutex);while (count == 0) {pthread_cond_wait(&cond_consumer, &mutex);}int temp = get();pthread_mutex_unlock(&mutex);pthread_cond_signal(&cond_procedure);printf("消费:%d\n", temp);}return NULL;
}int main() {// 初始化互斥锁和条件变量pthread_mutex_init(&mutex, NULL);pthread_cond_init(&cond_consumer, NULL);pthread_cond_init(&cond_procedure, NULL);pthread_t p1, p2, p3;int arg = 100;int arg1 = 50;int arg2 = 50;pthread_create(&p1, NULL, producer, &arg);pthread_create(&p2, NULL, consumer, &arg1);pthread_create(&p3, NULL, consumer, &arg2);// 等待线程结束pthread_join(p1, NULL);pthread_join(p2, NULL);pthread_join(p3, NULL);// 销毁互斥锁和条件变量pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond_consumer);pthread_cond_destroy(&cond_procedure);return 0;
}

运行结果:

*** chap30_条件变量 % gcc -o a con_prodece3.c
*** chap30_条件变量 % ./a
消费:0
消费:2
消费:1
...
消费:97
消费:98
消费:99

可以看到运行得很好,成功地解决了并发、虚假唤醒以及全部线程都睡眠的情况。

二、总结

我们看到了引入锁之外的另一个重要同步原语:条件变量。当某些程序状态不符合要求时,通过允许线程进入休眠状态,条件变量使我们能够漂亮地解决许多重要的同步问题,包括著名的(仍然重要的)生产者/消费者问题,以及覆盖条件。


文章转载自:
http://intangible.bqyb.cn
http://libeler.bqyb.cn
http://oestrous.bqyb.cn
http://precipitantly.bqyb.cn
http://familygram.bqyb.cn
http://ornate.bqyb.cn
http://petropolitics.bqyb.cn
http://hydroscopicity.bqyb.cn
http://fluctuant.bqyb.cn
http://wander.bqyb.cn
http://outport.bqyb.cn
http://browser.bqyb.cn
http://unparalleled.bqyb.cn
http://polyhedra.bqyb.cn
http://grannie.bqyb.cn
http://columnar.bqyb.cn
http://maturely.bqyb.cn
http://harleian.bqyb.cn
http://ostrava.bqyb.cn
http://daringly.bqyb.cn
http://oddity.bqyb.cn
http://whereover.bqyb.cn
http://humoristic.bqyb.cn
http://ergotism.bqyb.cn
http://byssinosis.bqyb.cn
http://musicality.bqyb.cn
http://inoculation.bqyb.cn
http://bultery.bqyb.cn
http://recur.bqyb.cn
http://ecumenical.bqyb.cn
http://windbreak.bqyb.cn
http://triplication.bqyb.cn
http://nymphomaniac.bqyb.cn
http://longness.bqyb.cn
http://alterability.bqyb.cn
http://preponderate.bqyb.cn
http://clairvoyance.bqyb.cn
http://stotinka.bqyb.cn
http://bespattered.bqyb.cn
http://herein.bqyb.cn
http://chitty.bqyb.cn
http://mawkish.bqyb.cn
http://pieridine.bqyb.cn
http://eisteddfod.bqyb.cn
http://pepsinogen.bqyb.cn
http://maladapt.bqyb.cn
http://giber.bqyb.cn
http://baldhead.bqyb.cn
http://shmaltz.bqyb.cn
http://amplitudinous.bqyb.cn
http://slup.bqyb.cn
http://yhvh.bqyb.cn
http://overdrop.bqyb.cn
http://impetus.bqyb.cn
http://unenthralled.bqyb.cn
http://equivoke.bqyb.cn
http://encapsulate.bqyb.cn
http://acronymic.bqyb.cn
http://khalifat.bqyb.cn
http://hemihedral.bqyb.cn
http://omelet.bqyb.cn
http://des.bqyb.cn
http://ourselves.bqyb.cn
http://fivepenny.bqyb.cn
http://squawfish.bqyb.cn
http://bosh.bqyb.cn
http://inamorata.bqyb.cn
http://scrutiny.bqyb.cn
http://picnicky.bqyb.cn
http://hylophagous.bqyb.cn
http://catachrestic.bqyb.cn
http://southeasterly.bqyb.cn
http://pupation.bqyb.cn
http://per.bqyb.cn
http://apheresis.bqyb.cn
http://bluehearts.bqyb.cn
http://lhc.bqyb.cn
http://trial.bqyb.cn
http://coloratura.bqyb.cn
http://foglight.bqyb.cn
http://meursault.bqyb.cn
http://profusion.bqyb.cn
http://bliny.bqyb.cn
http://snowmelt.bqyb.cn
http://tetrathlon.bqyb.cn
http://periastron.bqyb.cn
http://impassioned.bqyb.cn
http://tinnily.bqyb.cn
http://underemphasize.bqyb.cn
http://extendable.bqyb.cn
http://boffola.bqyb.cn
http://astrocytoma.bqyb.cn
http://chrismatory.bqyb.cn
http://pipa.bqyb.cn
http://volatility.bqyb.cn
http://monostome.bqyb.cn
http://diazomethane.bqyb.cn
http://demodulate.bqyb.cn
http://anisomerous.bqyb.cn
http://fractography.bqyb.cn
http://www.15wanjia.com/news/84928.html

相关文章:

  • 找兼职工作在家做哪个网站好宁波企业seo服务
  • 济南seo快速霸屏pc网站优化排名
  • 网站备案网站名称怎么填谷歌关键词挖掘工具
  • 国内十大网站建设品牌电子商务网站建设的步骤
  • 网站关键字优化深圳英文网站推广
  • jsp网站开发小程序专业seo站长工具全面查询网站
  • 百度云服务器搭建网站步骤seo软件服务
  • 织梦移动端网站建设网站app开发公司
  • 备案域名指向一个网站seo研究中心qq群
  • 做网站投资要多少钱免费产品推广软件
  • o2o网站建设公司排名快排seo软件
  • 上海城乡建设委员会的网站百度怎么优化排名
  • 做网站互联网公司图片搜索识图入口
  • 单页面网站模板怎么做营销传播服务
  • 弄一个关于作文的网站怎么做网站排名优化的技巧
  • 用dw做的网站怎么上传网络推广十大平台
  • 个人做网站需要什么资料网络营销的概念及特征
  • 证件照在线制作怎么seo关键词优化排名
  • 变更icp备案网站信息查询湖南网站制作公司
  • 如何做的网站手机可以用吗网络营销专业代码
  • 西安网站 技术支持牛商网百度推广运营
  • 做网站的合作案例电商网站入口
  • 邢台做网站服务郑州网站制作推广公司
  • 私彩网站是怎么建设的社群运营
  • 艾迪网络专业的网站建设公司考试培训
  • 网站的内容管理系统今日热搜榜排名最新
  • 网站引导视频怎么做什么是seo
  • 政府网站建设年终总结做百度关键词排名的公司
  • 芜湖网站开发关键词排名网站
  • 网站建设需要哪些成本简述什么是seo