进程(线程)间同步互斥经典问题(二)哲学家问题
2015-11-05 00:58
525 查看
问题描述:
哲学家问题,用于抽象死锁和资源耗尽问题:有n个叉子,n个哲学家,每个哲学家需要两把叉子才能吃饭。
他们围着圆桌坐,也就是每个人左手边右手边都有叉子,但是可能是同一把叉子。
每把叉子同时只能有一个人在用
问题分析:
主要是要考虑死锁和资源耗尽的问题:考虑死锁的情况,每个人都拿起叉子,那么都在睡觉等另一个哲学家放下叉子,那么所有的进程都在睡觉,没有进程能够唤醒,那么陷入死锁
考虑资源耗尽的情况,假设我们通过设置一个时间,让拿起叉子的哲学家自己醒来放下叉子,过一段时间再重新拿起,那么如果所有进程都同时开始执行,也会陷入一种死循环中,与死锁其实也是等同的了。
基本思路:
我们定义fork[MAX]表示每个叉子的状态,每个叉子有两个状态:脏:初始值,说明叉子没有被用过或者被当前持有者已经用过
净:表示已经被人拿起,但是还没有被用过
那么对于一个饿的科学家,他首先会询问两侧的勺子是否是干净的
如果是脏的,那么说明它已经被当前持有人用过,所以是已经可以被放下,那么我可以拿走,叉子被擦干净。
对于一个干净的叉子,一定是正在等待被使用的,所以我只能睡觉等它使用完后拿走它的脏叉子。
如果两个哲学家竞争同一资源时,让给编号小的哲学家
那么我们为了方便编程,考虑将上面的概念对应到信号量上,因为每个叉子同时只能有一个哲学家操作,才能保证不出现混乱,那么每个叉子需要一个锁,每个哲学家只有在它为脏的时候才能取,所以每个叉子作为一个初值为1的信号量即可。然后加一个互斥锁,防止死锁的出现。
代码如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <semaphore.h> #define MAX 5 #define TRUE 1 #define p(x) sem_wait(&x) #define v(x) sem_post(&x) /* sem_wait(&x) sem_wait是一个原子操作,它的作用使从信号量的值中减"1", 但它永远会先等待该信好两为一个非零值才开始做减法 sem_post(&x) 在不冲突的情况下,给信号量的值加上一个"1" */ sem_t forks[MAX];//记录叉子的状态,0代表干净,1代表脏 pthread_mutex_t mutex; void init ( ) { int i; //初始话信号量,叉子的初始状态是脏(1) for ( i = 0 ; i < MAX ; i++ ) sem_init( &forks[i] , 0 , 1 ); } //描述哲学家的操作的函数 void * philosopher ( void* arg ) { int* p = (int*)arg; int x = *p;//获得哲学家的id while ( TRUE ) { pthread_mutex_lock(&mutex); p(forks[x]);//如果叉子脏,那么由当前拿叉子的人擦干净拿来 p(forks[(x+1)%MAX]);//同上 printf ( "the %dth philosopher having meal...\n" , x ); sleep(1);//哲学家吃啊吃... v(forks[x]);//吃饭后弄脏了叉子 v(forks[(x+1)%MAX]);//同上 pthread_mutex_unlock(&mutex); sleep(2);//哲学家等自己变饿 } } int main ( ) { init ();//初始化叉子的状态 pthread_t id[MAX];//用来存每个哲学家线程的id int tid[MAX];//用来存每个哲学家的id int i; for ( i = 0 ; i < MAX ; i++ ) { tid[i] = i; //创建一个新的线程 pthread_create ( &id[i] , NULL , philosopher , &tid[i] ); } //设置主线程阻塞,等待每个哲学家线程 for ( i = 0 ; i < MAX ; i++ ) pthread_join ( id[i] , NULL ); }
相关文章推荐
- 应用领航:盘点那些年我们一起追过的OS
- 无奇不有!盘点各国自己开发的操作系统
- 可自定义oem的萝卜家园 Ghost XP 新春装机版 V200801 下载
- C#实现判断操作系统是否为Win8以上版本
- Linux操作系统添加新硬盘方法
- java如何获取本地操作系统进程列表
- Linux rdesktop操作系统下远程登录Windows XP桌面
- 32位操作系统认出超出4G内存的方法
- Linux rpm tar 操作系统下软件的安装与卸载方法
- JavaScript 获取用户客户端操作系统版本
- jsp 获取客户端的浏览器和操作系统信息
- Windows 操作系统的安全设置
- php判断当前操作系统类型
- c#线程同步使用详解示例
- PHP获取用户的浏览器与操作系统信息的代码
- Perl操作系统环境变量的脚本代码
- javascript获取本机操作系统类型的方法
- 封装好的js判断操作系统与浏览器代码分享
- javascript实现获取浏览器版本、操作系统类型
- Linux线程同步之信号C语言实例