linux多线程【3】哲学家用餐-mutex实现
来源:互联网 发布:系统功能优化调整 编辑:程序博客网 时间:2024/04/28 07:51
ref:
http://blog.csdn.net/kongzhp/article/details/7487150
5跟筷子,5个哲学家,哲学家要吃饭,自然要两根筷子,这样就出现资源争用的情况。哲学家只能用左边和右边的筷子,两根筷子备齐才能吃饭!
使用mutex的话,就是每个筷子一个mutex,需要5个mutex,哲学家先lock左边的筷子,如果有人已经在用那根筷子了,那就等着,不然左边的筷子就拿到手了,然后去拿右边的筷子,如果拿到了,那就开饭!如果拿不到,那就等一下再尝试,尝试累计10次的话,干脆放弃,把左边的筷子也放回去让别人先吃了再说!
如何检测是否真的lock成功了呢?那就是给筷子赋值,把自己的编号赋值给两根筷子,然后usleep一下,这个时候很可能线程调度,cpu把机会给了别的线程,假如没有lock住,那么可能筷子的值会发生意外的修改。假如一直没有被错误的修改,那么应该就已经lock 成功了咯!
在没有使用同步时,会发生很多意外修改的情况:
#include <pthread.h>#include <stdio.h>//#include<process.h>#include<errno.h>#define N 5#define M 10int cholk[N];pthread_mutex_t mt[N];void *func(void *);int main(){pthread_t person[N];int i;//init threadfor(i=0;i<N;i++){pthread_mutex_init(mt+i,NULL);}// create N threadsfor(i=0;i<N; i++){if(pthread_create(person+i, NULL, func, (void*)i)!=0 ){fprintf(stderr, "create error\n");exit(2);}}//wait for thread terminalfor(i=0;i<N;i++){pthread_join(*(person+i), NULL);}return 0;}void *func(void *p){while(1){int i=(int)p;int j=M;/*while(0 != pthread_mutex_trylock(mt+i) ){usleep(rand()%20);} // lock the left one!//pthread_mutex_lock(mt+i);while(j){if(0==pthread_mutex_trylock(mt +(i+1)%N ) ) // try to lock the right one, terminal after M times failsbreak;j--;}if(j==0) // fail,release the left one{pthread_mutex_unlock(mt+i);continue;}*/cholk[i]=i;cholk[(i+1)%N]=i;usleep(100); printf("The %d th person have dinner! %d,%d %s\n", i, cholk[i], cholk[(i+1)%N], (cholk[i]==cholk[(i+1)%N] && cholk[i]==i) ? "right":"wrong" );// after eat dinner, release both;//pthread_mutex_unlock(mt+i);//pthread_mutex_unlock(mt+(i+1)%N);usleep(10);}return NULL;}
同步以后:
#include <pthread.h>#include <stdio.h>//#include<process.h>#include<errno.h>#define N 5#define M 10int cholk[N];pthread_mutex_t mt[N];void *func(void *);int main(){pthread_t person[N];int i;//init threadfor(i=0;i<N;i++){pthread_mutex_init(mt+i,NULL);}// create N threadsfor(i=0;i<N; i++){if(pthread_create(person+i, NULL, func, (void*)i)!=0 ){fprintf(stderr, "create error\n");exit(2);}}//wait for thread terminalfor(i=0;i<N;i++){pthread_join(*(person+i), NULL);}return 0;}void *func(void *p){while(1){int i=(int)p;int j=M;while(0 != pthread_mutex_trylock(mt+i) ){usleep(rand()%20);} // lock the left one!//pthread_mutex_lock(mt+i);while(j){if(0==pthread_mutex_trylock(mt +(i+1)%N ) ) // try to lock the right one, terminal after M times failsbreak;j--;}if(j==0) // fail,release the left one{pthread_mutex_unlock(mt+i);continue;}cholk[i]=i;cholk[(i+1)%N]=i;usleep(100); printf("The %d th person have dinner! %d,%d %s\n", i, cholk[i], cholk[(i+1)%N], (cholk[i]==cholk[(i+1)%N] && cholk[i]==i) ? "right":"wrong" );// after eat dinner, release both;pthread_mutex_unlock(mt+i);pthread_mutex_unlock(mt+(i+1)%N);usleep(10);}return NULL;}
效果:
注意:
1.lock第一个筷子的时候,最好用pthread_mutex_lock,用try_lock的话应该用while循环加延时,但是这样的话try_lock就会反复去轮询,导致效率降低,而pthread_mutex_lock则会一直阻塞,就这么等着,不占用cpu时间。用try_lock,while循环,中间加入延时,效率有所改善,不然好多时间都消耗在轮询里。可见,多线程不仅要编的对,还要编的高效,需要对同步机制有细致的了解。
2.另外,有几次测试的时候,发现只有1和3交替吃饭,别人都没得吃!可能是其他两个usleep没有加入,所以呢,线程切换的时候,大部分都是在临界区里被切换出去,那么其他线程锁不住,最后还是切换回来,导致有的线程一直抢不到啊。
下图是0和2有饭吃,别的没得吃,这个是把所有usleep都注释掉的结果。
unlock以后usleep一下,就不会发生这种情况了。
- linux多线程【3】哲学家用餐-mutex实现
- Linux 多线程同步之哲学家用餐问题
- linux多线程【4】哲学家用餐-sem_t
- linux多线程【5】哲学家用餐-另一种思路
- Linux 多线程同步之哲学家用餐问题
- Linux 多线程同步之哲学家用餐问题
- Linux 多线程同步之哲学家用餐问题分析
- 哲学家用餐模型分析
- 哲学家用餐模型分析
- linux多线程编程3--mutex
- linux多线程编程3--mutex
- 哲学家用餐问题(Java)
- 多线程同步中的哲学家就餐问题 - linux 平台实现
- linux多线程-哲学家就餐问题
- Linux编程练习 --多线程3--mutex
- Linux编程练习 --多线程3--mutex
- Linux编程练习 --多线程3--mutex
- linux多线程之mutex
- axis1.4发布struts-config.wsdd文件
- 【Cocos2d-x 002】 实例学习之CCBlink
- Android 工具之mksdcard
- 项目2
- thinkpad e40 电源警报声的消除
- linux多线程【3】哲学家用餐-mutex实现
- onMeasure和onLayout
- cocos2d-x简单的runAction
- 恢复Ubuntu默认的面板
- 如何查看Linux系统中的 LABEL/UUID
- sql 查询关键字大团圆
- 关于腾讯敏捷框架TAPD(Tencent Agile Product Development)
- 使用GDI+保存图像为8bpp的灰度图像
- c# 验证文件签名是否成功,获取签名时间戳