哲学家就餐问题--信号量和互斥量预防死锁
生活随笔
收集整理的這篇文章主要介紹了
哲学家就餐问题--信号量和互斥量预防死锁
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
哲學(xué)家就餐問題可以采取預(yù)防死鎖的方案,就是使用互斥量和信號(hào)量鎖定資源。
互斥量:
對(duì)資源進(jìn)行鎖定的意思就是說,當(dāng)一個(gè)哲學(xué)家使用叉子的時(shí)候,他首先要先把叉子鎖定,然后,拿起來。這個(gè)時(shí)候如果別的哲學(xué)家也來拿相同的叉子,發(fā)現(xiàn),該叉子是被互斥量鎖定了,不能夠拿,那么,他就不會(huì)來?yè)屨歼@個(gè)叉子,而是在排等待隊(duì)列中。這樣就可以避免死鎖的發(fā)生。
信號(hào)量:
同樣,沒有資源的時(shí)候,信號(hào)量的值是0,有的時(shí)候就不斷地加1。“0,1”信號(hào)和互斥量是相似的。
使用互斥量預(yù)防死鎖代碼:
/***哲學(xué)家吃飯問題:幾個(gè)哲學(xué)家吃飯,假定哲學(xué)家有五個(gè)人,這五個(gè)哲學(xué)家坐在一張圓桌上面,*每個(gè)哲學(xué)家的左手旁邊都放有一個(gè)叉子(fork),那么,這圍城一圈的五個(gè)哲學(xué)家有五個(gè)叉子*。每個(gè)哲學(xué)家有三種狀態(tài),thinking(思考),trying(嘗試去拿叉子吃飯),eating(已*經(jīng)拿起叉子,正在吃飯)。每次吃飯需要兩個(gè)叉子,也就是哲學(xué)家左右手邊的叉子。* *//*** 本例使用pthread庫(kù)實(shí)現(xiàn)哲學(xué)家進(jìn)餐的問題。* *//***在這個(gè)例子中使用互斥量解決死鎖問題。 * */#include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <sys/wait.h>//為了使用sleep()函數(shù) #include <unistd.h>//參數(shù)的識(shí)別 #include <getopt.h> //長(zhǎng)命令的解析//哲學(xué)家的數(shù)目 int Number;//聲明共享變量fork,其中fork的數(shù)目和哲學(xué)家數(shù)目是相同的 pthread_mutex_t *pfork;//定義一個(gè)philosopher的三個(gè)狀態(tài) #define Thinking 1 #define Trying 2 #define Eating 3int *state;void *EatMeal();//得到參數(shù) void GetArg(char* argv[] /*in*/,int* number /*out*/); void main(int argc, char* argv[]) {int k =0;while(k<1){int option_index = 0;int rvalue = 0;struct option long_option[] = {{"normal",0,0,0 },{"method1",0,0,0},{"method2",0,0,0}};rvalue = getopt_long_only(argc,argv, "a:bc::", long_option,&option_index);switch(option_index){case 0 : printf("%s\n",long_option[option_index].name);break;case 1 : printf("%s\n",long_option[option_index].name);break;case 2 : printf("%s\n",long_option[option_index].name);break;}k++;}GetArg(argv, &Number);pfork = malloc(Number*sizeof(pthread_mutex_t));state = malloc(Number*sizeof(int));//聲明進(jìn)程數(shù)組,每一個(gè)進(jìn)程代表一個(gè)哲學(xué)家 pthread_t philosopher[Number];int i;//初始化每一個(gè)資源實(shí)例for( i = 0; i < Number; i++){pthread_mutex_init(&pfork[i],NULL);}//創(chuàng)建和哲學(xué)家數(shù)量想對(duì)應(yīng)的進(jìn)程,并且每個(gè)進(jìn)程開始進(jìn)行吃飯的活動(dòng)for( i = 0; i < Number; i++){//記錄當(dāng)前進(jìn)程的編號(hào),并傳遞到Meal()函數(shù)中int j = i;pthread_create(&philosopher[i], NULL, EatMeal, &j);printf("I am philosopher %d\n", j);}//將所有的進(jìn)程進(jìn)行Join操作。for( i=0; i < Number; i++){pthread_join(philosopher[i], NULL);}//退出程序pthread_exit(0);return ;}void *EatMeal(int *i) {//記錄當(dāng)前的線程id號(hào)int id = *i;state[id] = Thinking; //線程初始化的時(shí)候?yàn)門hinkingint leftFork = (id + Number -1) % Number;int rightFork = (id + Number +1) % Number;int mealTime = 5;int mymealTime = 0;while (mymealTime < mealTime) //每個(gè)philosopher必須吃得符合規(guī)定 {if(state[id] == Thinking){printf("Philosopher %d is thinking\n", id);sleep(1);state[id] = Trying;}else if(state[id] == Trying){printf("Philosopher %d is Trying\n", id);sleep(1);pthread_mutex_lock(&pfork[leftFork]);pthread_mutex_lock(&pfork[rightFork]);state[id] = Eating;}else {printf("Philosopher %d is Eating\n", id);sleep(1);mymealTime++;pthread_mutex_unlock(&pfork[leftFork]);pthread_mutex_unlock(&pfork[rightFork]);}}}void GetArg(char * argv[],int* number) {*number = strtol(argv[1], NULL, 10); } View Code使用信號(hào)量預(yù)防死鎖代碼:
/***哲學(xué)家吃飯問題:幾個(gè)哲學(xué)家吃飯,假定哲學(xué)家有五個(gè)人,這五個(gè)哲學(xué)家坐在一張圓桌上面,*每個(gè)哲學(xué)家的左手旁邊都放有一個(gè)叉子(fork),那么,這圍城一圈的五個(gè)哲學(xué)家有五個(gè)叉子*。每個(gè)哲學(xué)家有三種狀態(tài),thinking(思考),trying(嘗試去拿叉子吃飯),eating(已*經(jīng)拿起叉子,正在吃飯)。每次吃飯需要兩個(gè)叉子,也就是哲學(xué)家左右手邊的叉子。* *//*** 本例使用信號(hào)量解決哲學(xué)家進(jìn)餐的問題。* 哲學(xué)家的數(shù)目和叉子的數(shù)目相等。* 叉子是幾個(gè)哲學(xué)家共享的資源,將這些資源聲明為信號(hào)量,其中每一個(gè)資源為一個(gè)信號(hào)量,* 本例中的信號(hào)量為0和1兩個(gè)值,當(dāng)信號(hào)量為0的時(shí)候,是不能夠被另外一個(gè)進(jìn)程使用,當(dāng)* 信號(hào)兩為1的時(shí)候,可以被使用。* */ #include <stdio.h> #include <pthread.h> #include <math.h> #include <sys/time.h> #include <semaphore.h> #include <stdlib.h> //設(shè)定哲學(xué)家的數(shù)目 int Number;//定義哲學(xué)家的三種狀態(tài) #define Thinking 1 #define Trying 2 #define Eating 3pthread_mutex_t mutex; //聲明一個(gè)互斥量,用來在使用資源的時(shí)候鎖住 sem_t *semph; //為每一個(gè)叉子定義信號(hào)量int *state; //記錄每一個(gè)哲學(xué)家的狀態(tài)//得到參數(shù) void GetArg(char* argv[];int* number; );void main(int argc, char* argv[]) {GetArg(argv, &Number);semph = malloc(Number* sizeof(sem_t));state = malloc(Number* sizeof(int));pthread_t philosopher[Number]; //為每一個(gè)哲學(xué)家聲明一個(gè)進(jìn)程 pthread_mutex_init(&mutex, NULL); //初始化互斥量void * EatMeal(); //哲學(xué)家操作的主要函數(shù)int i =0;for(i = 0; i < Number; i++){int j = i;sem_init(&semph[i], 0, 1);// 初始化信號(hào)量,信號(hào)量的值為0或者1//創(chuàng)建進(jìn)程,每個(gè)進(jìn)程執(zhí)行函數(shù)EatMeal()中的操作int res = pthread_create(&philosopher[i], NULL, EatMeal, &j); printf("This is thread %d \n",i);/*//檢查是否創(chuàng)建進(jìn)程成功if(res !=0){printf("%d sucess!\n", i);}*/}for(i = 0; i < Number; i++){pthread_join(philosopher[i], NULL);}pthread_exit(0);//sleep(100);//主要進(jìn)程執(zhí)行等待的任務(wù)(應(yīng)該修改,直到每一個(gè)線程都被完成主進(jìn)程才結(jié)束) }//定義哲學(xué)家吃飯的這個(gè)問題 void *EatMeal(int *j) {int phiD = *j; //記錄哲學(xué)家的id號(hào)int leftPhi; //記錄哲學(xué)家左邊的叉子的id號(hào)int rightPhi; //記錄哲學(xué)家右邊的叉子的id號(hào) leftPhi = (phiD + Number - 1) % Number;rightPhi = (phiD + Number + 1) % Number;state[phiD] = Thinking; //哲學(xué)家的初始狀態(tài)設(shè)為 Thinkingint mymealCount = 0;int mealCount = 1;double time;while(mymealCount < mealCount) //規(guī)定每個(gè)人吃飯不能超過最大吃飯次數(shù) {time = (rand()%9 + 1)/100.0; //得到的時(shí)間在0.01 - 0.1之間//如果當(dāng)前的狀態(tài)是Thinking,那么則轉(zhuǎn)化為Trying的狀態(tài)int i = state[phiD];//記錄當(dāng)前的狀態(tài)if(state[phiD] == Thinking){printf("%d philosopher is thinking!\n", phiD);sleep(1);//在這個(gè)狀態(tài)停留一段時(shí)間state[phiD] = Trying;}//如果當(dāng)前的狀態(tài)是Trying,則檢查是否能夠達(dá)到Eating的狀態(tài)else if(state[phiD] == Trying){printf("%d philosopher is trying!\n",phiD);sleep(1);//在這個(gè)狀態(tài)停留一段時(shí)間if(!sem_wait(&semph[leftPhi]))//如果能夠拿起哲學(xué)家左邊的叉子 {if(!sem_wait(&semph[rightPhi]))//也能夠拿起右邊的叉子 {state[phiD] = Eating;}else//不能拿起右邊的叉子 {sem_post(&semph[leftPhi]);//放下左邊的叉子 }}}else //狀態(tài)為 Eating {printf("%d philosopher is eating!\n",phiD);sleep(1);//先吃一段時(shí)間sem_post(&semph[leftPhi]);//放下左邊的叉子sem_post(&semph[rightPhi]);//放下右邊的叉子state[phiD] = Thinking;mymealCount++;}if(i != state[phiD]){pthread_mutex_lock(&mutex);printf("%d state tranformed from %d to %d\n", phiD, i, state[phiD]);pthread_mutex_unlock(&mutex);}} }void GetArg(char* argv[],int* number) {*number = strtol(argv[1], NULL, 10); } View Code?
轉(zhuǎn)載于:https://www.cnblogs.com/SevenwindMa/p/3485129.html
總結(jié)
以上是生活随笔為你收集整理的哲学家就餐问题--信号量和互斥量预防死锁的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于visual Studio2013解
- 下一篇: HTML5本地存储localstorag