多线程编程-条件变量
来源:互联网 发布:java特种兵有没有下册 编辑:程序博客网 时间:2024/04/27 11:38
有的时候仅仅依靠锁住共享资源来使用它是不够的。有时候共享资源只有某些状态的时候才能够使用。比方说,某个线程如果要从堆栈中读取数据,那么如果栈中没有数据就必须等待数据被压栈。这种情况下的同步使用互斥锁
是不够的。另一种同步的方式--条件变量,就可以使用在这种情况下。
条件变量的使用总是和互斥锁及共享资源联系在一起的。线程首先锁住互斥锁,然后检验共享资源的状态是否处于可使用的状态。如果不是,那么线程就要等待条件变量。要指向这样的操作就必须在等待的时候将互斥锁解锁,以
便其他线程可以访问共享资源并改变其状态。它还得保证从等到得线程返回时互斥体是被上锁得。当另一个线程改变了共享资源的状态时,它就要通知正在等待条件变量的线程,使之重新变回被互斥锁阻塞的线程。
假设有共享的资源sum,与之相关联的mutex 是lock_s.假设每个线程对sum的操作很简单的,与sum的状态无关,比如只是sum++.那么只用mutex足够了.程序员只要确保每个线程操作前,取得lock,然后sum++,再unlock即可.每个线程
的代码将像这样
- add()
- {
- pthread_mutex_lock(lock_s);
- sum++;
- pthread_mutex_unlock(lock_s);
- }
如果操作比较复杂,假设线程t0,t1,t2的操作是sum++,而线程t3则是在sum到达100的时候,打印出一条信息,并对sum清零.这种情况下,如果只用mutex, 则t3需要一个循环,每个循环里先取得lock_s,然后检查sum的状态,如果sum>=100,
则打印并清零,然后unlock.如果sum<100,则unlock,并sleep()本线程合适的一段时间.
这个时候,t0,t1,t2的代码不变,t3的代码如下
- print()
- {
- while(1)
- {
- pthread_mutex_lock(lock_s);
- if(sum >= 100)
- {
- printf(“sum has reached 100!”);
- sum = 0;
- pthread_mutex_unlock(lock_s);
- }
- else
- {
- pthread_mutex_unlock(lock_s);
- sleep(100);
- }
- }
- }
这种办法有两个问题
1) sum在大多数情况下不会到达100,那么对t3的代码来说,大多数情况下,走的是else分支,只是lock和unlock,然后sleep().这浪费了CPU处理时间.
2) 为了节省CPU处理时间,t3会在探测到sum没到达100的时候sleep()一段时间.这样却又带来另外一个问题,亦即t3响应速度下降.可能在sum到达200的时候,t3才会醒过来.
这样,程序员在设置sleep()时间的时候陷入两难境地,设置得太短了节省不了资源,太长了又降低响应速度.真是难办啊!
这个时候,condition variable内裤外穿,从天而降,拯救了焦头烂额的你. 你可以首先定义一个condition variable.
pthread_cond_t cond_sum_ready = PTHREAD_COND_INITIALIZER;
t0,t1,t2的代码只要后面加两行,像这样
- add()
- {
- pthread_mutex_lock(lock_s);
- sum++;
- if(sum >= 100)
- {
- pthread_cond_signal(&cond_sum_ready);
- }
- pthread_mutex_unlock(lock_s);
- }
而t3的代码则是
- print
- {
- pthread_mutex_lock(lock_s);
- while(sum < 100)
- {
- pthread_cond_wait(&cond_sum_ready, &lock_s);
- }
- printf(“sum is over 100!”);
- sum = 0;
- pthread_mutex_unlock(lock_s);
- }
注意两点:
1) 在thread_cond_wait()之前,必须先lock相关联的mutex, 因为假如目标条件未满足,pthread_cond_wait()实际上会unlock该mutex, 然后block,当目标变量被唤醒的时候才会再重新lock该mutex, 然后返回.
2) 为什么是while(sum < 100),而不是if(sum < 100) ?这是因为在pthread_cond_signal()和pthread_cond_wait()返回之间,有时间差,假设在这个时间差内发生了唤醒拦截:还有另外一个线程t4又把sum减少到100以下了,那么t3在pthread_cond_wait()返回之后,显然应该再检查一遍sum的大小.这就是用while的用意,如果sum减少到了100以下,就会再次进入pthread_cond_wait方法.
#include <pthread.h>#include <stdio.h>#include <stdlib.h>static int sum = 0;pthread_mutex_t lock_s = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t cond_sum_ready = PTHREAD_COND_INITIALIZER;void add(void){pthread_mutex_lock(&lock_s);sum++;printf("tid=%d, sum=%d\n",pthread_self(),sum);if(sum >= 100){pthread_cond_signal(&cond_sum_ready);}pthread_mutex_unlock(&lock_s);}void print(void){pthread_mutex_lock(&lock_s);while(sum < 100){pthread_cond_wait(&cond_sum_ready, &lock_s);}printf("sum is over 100!\n");sum = 0;pthread_mutex_unlock(&lock_s);}void *fn_1(void* arg){int i;for(i = 0; i < 100; i++){usleep(10);add();}return ((void *)0);}void *fn_2(void *arg){int i;for(i = 0; i < 100; i++){usleep(20);add();}return ((void *)0);}void *fn_3(void *arg){int i;for(i = 0; i < 100; i++){usleep(30);add();}return ((void *)0);}void *fn_4(void *arg){for(;;){print();}return ((void *)0);}int main(void){void *ret;int err;pthread_t tid1, tid2, tid3, tid4;err = pthread_create(&tid1, NULL, fn_1, NULL);if (err != 0)err_quit("can't create thread 1: %s\n", strerror(err));err = pthread_create(&tid2, NULL, fn_2, NULL);if (err != 0)err_quit("can't create thread 2: %s\n", strerror(err));err = pthread_create(&tid3, NULL, fn_3, NULL);if (err != 0)err_quit("can't create thread 3: %s\n", strerror(err));err = pthread_create(&tid4, NULL, fn_4, NULL);if (err != 0)err_quit("can't create thread 4: %s\n", strerror(err));pthread_join(tid3, &ret);exit(0);}
- 多线程编程-条件变量
- 多线程编程: 条件变量
- 多线程编程-条件变量
- Linux多线程编程-条件变量
- linux多线程编程---条件变量
- 多线程编程-条件变量pthread_cond_t
- Linux多线程编程-条件变量
- Linux多线程编程---条件变量
- boost多线程编程条件变量
- c++ 多线程编程 条件变量
- Linux编程练习 --多线程4--条件变量
- Linux多线程编程下的条件变量
- 多线程编程学习笔记----条件变量
- 多线程编程,条件变量pthread_cond_t应用(转)
- linux多线程编程4--条件变量
- 多线程编程,条件变量pthread_cond_t应用
- Linux编程练习 --多线程4--条件变量
- posix多线程编程之条件变量
- Windows系统下如何使用makefile
- 弹窗代码大全 弹窗广告代码
- 嵌入式操作系统内核原理和开发(事件)
- Eclipse集成开发环境如何与android手机连接的一个解决办法
- WinPcap 中文技术文档(4.1.2) 第三章
- 多线程编程-条件变量
- N9:Fix wxWidgets2.9.4 wxSocketServer WaitForAccept
- Linux下minicom的配置和使用方法 安装配置minicom
- UnicodeReader解决TXT文件读出时有一个乱码的问题
- WinPcap 中文技术文档(4.1.2) 第四章
- perl
- 甘特图 横道图
- WinPcap 中文技术文档(4.1.2)第五章
- MicroSoft 12个球一个天平,现知道只有一个和其它的重量不同,问怎样称才能用三次就找到那个球?那13个呢?