Linux经典问题—五哲学家就餐问题
http://m.blog.csdn.net/aspenstars/article/details/70149038
一、問題介紹
? ? ? ?由Dijkstra提出并解決的哲學家進餐問題(The Dinning Philosophers Problem)是典型的同步問題。該問題是描述有五個哲學家共用一張圓桌,分別坐在周圍的五張椅子上,在圓桌上有五個碗和五只筷子,他們的生活方式是交替地進行思考和進餐。平時,一個哲學家進行思考,饑餓時便試圖取用其左右最靠近他的筷子,只有在他拿到兩只筷子時才能進餐。進餐完畢,放下筷子繼續思考。
二、POSIX中的互斥量
1、庫文件:#include <pthread.h>
2、數據類型:
pthread_mutex_t???????//互斥量
pthread_mutexattr_t???//互斥量的屬性
3、互斥量相關的函數:
①intpthread_mutex_init(pthread_mutex_t*mutex,constpthread_mutexattr_t *attr);//對一個互斥量進行初始化 ②intpthread_mutex_destroy(pthread_mutex_t*mutex);//銷毀一個互斥量;返回值:成功則返回0,否則返回錯誤編號 ③intpthread_mutex_lock(pthread_mutex_t *mutex); ④intpthread_mutex_trylock(pthread_mutex_t *mutex); ⑤intpthread_mutex_unlock(pthread_mutex_t *mutex);//返回值:成功則返回0,否則返回錯誤編號;這三個函數用于對互斥量進行加鎖解鎖。其中pthread_mutex_trylock是非阻塞的加鎖函數,若加鎖失敗,則立即返回EBUSY。 4、示例//…
pthread_mutex_tmutex;
pthread_mutex_init(&mutex, NULL);
pthread_mutex_lock(&mutex);
//do something
pthread_mutex_unlock(&mutex);
pthread_mutex_destroy(&mutex);
//…
三、POSIX線程函數
1、庫文件:#include<pthread.h>
2、數據類型:pthread_t;線程ID
3、線程相關函數:
①pthread_tpthread_self();//返回調用線程的線程ID ②intpthread_create(pthread_t?*tidp,?constpthread_attr_tattr, void *(*start_rtn)(void*), void *arg);//線程創建函數,tidp,用于返回線程ID;attr,線程屬性,若設為NULL,則線程使用默認屬性;start_rtn是線程例程函數,arg為線程函數參數。 ③voidpthread_exit(void *rval_ptr);//rval_ptr指向線程返回值。線程退出有以下幾種情況:
a.線程從例程函數返回。 b.線程被其它線程取消。 c.線程調用pthread_exit()主動退出。 ④intpthread_join(pthread_t?thread, void **rval_ptr);//返回值:成功返回0,錯誤返回錯誤編號;此函數用于等待指定線程(由參數thread指定)運行結束,期間,調用線程將會阻塞。rval_ptr參數用于獲取線程返回值。 四、Linux信號量1、庫文件:#include<semaphore.h>
2、信號量數據類型:sem_t
3、主要函數: ①sem_init(sem_t*sem, int pshared, unsigned int value);//初始化一個無名信號量 ②sem_destroy(sem_t*sem);//銷毀一個無名信號量;返回值:成功返回 0;錯誤返回 -1,并設置errno? ③sem_post(sem_t?*sem);//信號量值加1。若有線程阻塞于信號量sem,則調度器會喚醒對應阻塞隊列中的某一個線程。 ④sem_wait(sem_t?*sem);//若sem小于0,則線程阻塞于信號量sem,直到sem大于0。否則信號量值減1。 ⑤sem_trywait(sem_t?*sem);//功能同sem_wait(),但此函數不阻塞,若sem小于0,直接返回;返回值:成功返回0,錯誤返回-1,并設置errno? 4、示例sem_tsem;
sem_init(&sem,0, 1);//初始化一個值為1的信號量
sem_wait(&sem);//獲取信號量
//dosomthing
sem_post(&sem);//釋放信號量
sem_destroy(&sem);//銷毀一個無名信號量
五、流程圖
六、代碼示例
使用互斥量:
| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 | #include <stdio.h>#include <stdlib.h>#include <memory.h>#include <pthread.h>#include <errno.h>#include <math.h>//筷子作為mutexpthread_mutex_t chopstick[6] ;void *eat_think(void *arg){ char phi = *(char *)arg; int left,right; //左右筷子的編號 switch (phi){ case 'A': left = 5; right = 1; break; case 'B': left = 1; right = 2; break; case 'C': left = 2; right = 3; break; case 'D': left = 3; right = 4; break; case 'E': left = 4; right = 5; break; } int i; for(;;){ usleep(3); //思考 pthread_mutex_lock(&chopstick[left]); //拿起左手的筷子 printf("Philosopher %c fetches chopstick %d\n", phi, left); if (pthread_mutex_trylock(&chopstick[right]) == EBUSY){ //拿起右手的筷子 pthread_mutex_unlock(&chopstick[left]); //如果右邊筷子被拿走放下左手的筷子 continue; } // pthread_mutex_lock(&chopstick[right]); //拿起右手的筷子,如果想觀察死鎖,把上一句if注釋掉,再把這一句的注釋去掉 printf("Philosopher %c fetches chopstick %d\n", phi, right); printf("Philosopher %c is eating.\n",phi); usleep(3); //吃飯 pthread_mutex_unlock(&chopstick[left]); //放下左手的筷子 printf("Philosopher %c release chopstick %d\n", phi, left); pthread_mutex_unlock(&chopstick[right]); //放下左手的筷子 printf("Philosopher %c release chopstick %d\n", phi, right); pthread_mutex_destroy(&chopstick[left]); pthread_mutex_destroy(&chopstick[right]); }}int main(){ pthread_mutex_t A,B,C,D,E; //5個哲學家 int i; for (i = 0; i < 5; i++) pthread_mutex_init(&chopstick[i],NULL); pthread_create(&A,NULL, eat_think, "A"); pthread_create(&B,NULL, eat_think, "B"); pthread_create(&C,NULL, eat_think, "C"); pthread_create(&D,NULL, eat_think, "D"); pthread_create(&E,NULL, eat_think, "E"); pthread_join(A,NULL); pthread_join(B,NULL); pthread_join(C,NULL); pthread_join(D,NULL); pthread_join(E,NULL); return 0;} |
?來自CODE的代碼片 Phli.c
使用信號量:| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 | #include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <semaphore.h> sem_t chopstick[6] ;void *eat_think(void *arg){ char phi = *(char *)arg; int left,right; switch (phi){ case 'A': left = 5; right = 1; break; case 'B': left = 1; right = 2; break; case 'C': left = 2; right = 3; break; case 'D': left = 3; right = 4; break; case 'E': left = 4; right = 5; break; } int i; for(;;){ usleep(3); sem_wait(&chopstick[left]); printf("Philosopher %c fetches chopstick %d\n", phi, left); if (sem_trywait(&chopstick[right]) < 0){ sem_post(&chopstick[left]); continue; } printf("Philosopher %c fetches chopstick %d\n", phi, right); printf("Philosopher %c is eating.\n",phi); usleep(3); sem_post(&chopstick[left]); printf("Philosopher %c release chopstick %d\n", phi, left); sem_post(&chopstick[right]); printf("Philosopher %c release chopstick %d\n", phi, right); }}int main(){ pthread_t A,B,C,D,E; int i; for (i = 0; i < 5; i++) sem_init(&chopstick[i],0,1); pthread_create(&A,NULL, eat_think, "A"); pthread_create(&B,NULL, eat_think, "B"); pthread_create(&C,NULL, eat_think, "C"); pthread_create(&D,NULL, eat_think, "D"); pthread_create(&E,NULL, eat_think, "E"); pthread_join(A,NULL); pthread_join(B,NULL); pthread_join(C,NULL); pthread_join(D,NULL); pthread_join(E,NULL); return 0;} |
總結
以上是生活随笔為你收集整理的Linux经典问题—五哲学家就餐问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 原神踏鞴砂铁门在哪
- 下一篇: 成都欢乐谷离哪个火车站近