哲學家用餐模型

分析:

為了避免死鎖,做了如下規定:每個哲學家先拿自己左手邊的筷子,然后再去拿右手邊的筷子,如果不能同時得到兩支筷子,則該哲學家放下手中已有的筷子。這種規定依然會因為振蕩而產生死鎖,例如:每個哲學家都同時拿上了左手邊的筷子,然后都阻塞,都釋放左手筷子;然后又同時去拿左手邊的筷子,這樣周而復始,一直進行下去,就是因為振蕩而產生的死鎖。解決方法:規定其中一位哲學家先拿右手邊的筷子,再拿左手邊的筷子即可。這樣即使最壞的情況下,也至少有一位哲學家可以拿到兩支筷子,而只要有一位哲學家拿到了兩支筷子,就肯定不會出現死鎖。

在這里筷子是臨界資源,即只能被哲學家互斥訪問,因此可以將筷子作為互斥量或者信號量。五支筷子應該引入五個互斥量,或者5個信號量(初始值為1)。將五個哲學家當成五個線程,其編號為i(0、1、2、3、4),互斥量或信號量編號也為0、1、2、3、4。則按照規定:i=0~3時,先拿i,再拿i+1i=4時,先拿0,再拿i。在此基礎上,對于每一個線程,如果不能同時拿上兩支筷子,則放棄已獲得的筷子,則:第一次用lock函數,采用阻塞加鎖;第二次拿筷子用trylock函數,采用非阻塞加鎖,并且釋放掉已經拿掉的筷子。

注意:互斥量、信號量既可以用于進程間同步,也可以用于線程間同步(一般來說,進程間同步信號量用的多一點);條件變量需要結合互斥量使用;讀寫鎖用于線程間同步,而文件鎖用于進程間同步。

下面線程版采用互斥量,進程版采用信號量

//線程版哲學家用餐模型

#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>pthread_mutex_t mutex[5];void *tfn( void *arg )
{int i = (int)arg;int ret;while(1) {if( i<4 ){pthread_mutex_lock( &mutex[i] );ret = pthread_mutex_trylock( &mutex[i+1] );if( ret != 0){//printf("The %dth philosopher missed the second chopstick!\n", i+1);pthread_mutex_unlock( &mutex[i] );}else{printf("Very good, the %dth philosopher has a pair of chopsticks to eat food!\n", i+1);sleep(5);pthread_mutex_unlock( &mutex[i] );pthread_mutex_unlock( &mutex[i+1] );//break;}}else{pthread_mutex_lock( &mutex[0] );ret = pthread_mutex_trylock( &mutex[i] );if( ret != 0){//printf("The %dth philosopher missed the second chopstick!\n", i+1);pthread_mutex_unlock( &mutex[0] );}else{printf("Very good, the %dth philosopher has a pair of chopsticks to eat food!\n", i+1);sleep(5);pthread_mutex_unlock( &mutex[i] );pthread_mutex_unlock( &mutex[0] );//break;}}}return NULL;
}int main( void )
{int i, ret;pthread_t phi[5];pthread_attr_t attr;ret = pthread_attr_init( &attr );if( ret != 0 ){fprintf(stderr,"pthread_attr_init error: %s.\n", strerror(ret));exit(1);}ret = pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );if( ret != 0 ){fprintf(stderr,"pthread_attr_detach error: %s.\n", strerror(ret));exit(1);}for( i=0; i<5; i++){ret =  pthread_mutex_init( &mutex[i], NULL );if( ret != 0 ){fprintf(stderr,"pthread_mutex_init error: %s.\n", strerror(ret));exit(1);}}for( i=0; i<5; i++){ret = pthread_create( &phi[i], &attr, tfn, (void *)i );if( ret != 0 ){fprintf(stderr,"pthread_create error: %s.\n", strerror(ret));exit(1);}}pthread_attr_destroy( &attr );pthread_exit( NULL );
}

[root@localhost 02_pthread_sync_test]# ./philosophy_pthrd

Very good, the 2th philosopher has a pair of chopsticks to eat food!

Very good, the 4th philosopher has a pair of chopsticks to eat food!

Very good, the 1th philosopher has a pair of chopsticks to eat food!

Very good, the 3th philosopher has a pair of chopsticks to eat food!

Very good, the 3th philosopher has a pair of chopsticks to eat food!

Very good, the 1th philosopher has a pair of chopsticks to eat food!

Very good, the 1th philosopher has a pair of chopsticks to eat food!

Very good, the 3th philosopher has a pair of chopsticks to eat food!

Very good, the 3th philosopher has a pair of chopsticks to eat food!

Very good, the 1th philosopher has a pair of chopsticks to eat food!

//進程版哲學家用餐模型

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/mman.h>
#include <sys/wait.h>int main(void)
{int i;pid_t pid;sem_t *s;s = mmap(NULL, sizeof(sem_t)*5, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0);if (s == MAP_FAILED) {perror("fail to mmap");exit(1);}for (i = 0; i < 5; i++)sem_init(&s[i], 0, 1);  //信號量初值制定為1,信號量,變成了互斥鎖for (i = 0; i < 5; i++)if ((pid = fork()) == 0)break;if (i < 5) {                            //子進程int l, r;srand(time(NULL));if (i == 4)l = 0, r = 4;elsel = i, r = i+1;while (1) {sem_wait(&s[l]);if (sem_trywait(&s[r]) == 0) {printf(" %c is eating\n", 'A'+i);sem_post(&s[r]);}sem_post(&s[l]);sleep(rand() % 5);}exit(0);}for (i = 0; i < 5; i++)wait(NULL);for (i = 0; i < 5; i++)sem_destroy(&s[i]);munmap(s, sizeof(sem_t)*5);return 0;
}

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/385272.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/385272.shtml
英文地址,請注明出處:http://en.pswp.cn/news/385272.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【C++ Primer | 16】std::move和std::forward、完美轉發

右值引用應該是C11引入的一個非常重要的技術&#xff0c;因為它是移動語義&#xff08;Move semantics&#xff09;與完美轉發&#xff08;Perfect forwarding&#xff09;的基石&#xff1a; 移動語義&#xff1a;將內存的所有權從一個對象轉移到另外一個對象&#xff0c;高效…

循環引用

1. 測試代碼 #include <iostream> #include <memory> using namespace std;class B; class A { public:shared_ptr<B> pb;~A() { cout << "kill A\n";} };class B { public:shared_ptr<A> pa;~B() { cout << "kill B\n&q…

8. 字符串轉換整數 (atoi)

請你來實現一個 atoi 函數&#xff0c;使其能將字符串轉換成整數。 首先&#xff0c;該函數會根據需要丟棄無用的開頭空格字符&#xff0c;直到尋找到第一個非空格的字符為止。 當我們尋找到的第一個非空字符為正或者負號時&#xff0c;則將該符號與之后面盡可能多的連續數字組…

【C++ Primer | 16】容器適配器全特化、偏特化

上面對模板的特化進行了總結。那模板的偏特化呢&#xff1f;所謂的偏特化是指提供另一份模板定義式&#xff0c;而其本身仍為模板&#xff1b;也就是說&#xff0c;針對模板參數更進一步的條件限制所設計出來的一個特化版本。這種偏特化的應用在STL中是隨處可見的。比如 1.測試…

select、poll、epoll優缺點

select的缺點&#xff1a; 單個進程能夠監視的文件描述符的數量存在最大限制&#xff0c;通常是1024&#xff0c;當然可以更改數量&#xff0c;但由于select采用輪詢的方式掃描文件描述符&#xff0c;文件描述符數量越多&#xff0c;性能越差&#xff1b;內核/用戶空間內存拷貝…

vector源碼剖析

一、vector定義摘要&#xff1a; template <class T, class Alloc alloc> class vector { public:typedef T value_type;typedef value_type* pointer;typedef const value_type* const_pointer;typedef value_type* iterator;typ…

vs2013編譯win-32位下的libevent-2.0.21-stable,debug版本

環境&#xff1a;win10&#xff08;64位&#xff09;vs2013 首先需要修改Makefile.nmake中的CFLAGS$(CFLAGS) /Ox /W3 /wd4996 /nologo注釋掉&#xff0c;這一行是不帶調試信息的。CFLAGS$(CFLAGS) /Od /W3 /wd4996 logo /Zi 替換這一行之后就可以自帶調試信息。 打開vs2013的…

Leetcode 219. 存在重復元素 II

解題思路&#xff1a; class Solution { public:bool containsNearbyDuplicate(vector<int>& nums, int k) {unordered_map<int, int> cnt;for(int i0; i<nums.size(); i){if(cnt.find(nums[i]) ! cnt.end()){if(i - cnt[nums[i]] < k) return true;}cn…

Linux程序設計01:開發工具和開發平臺

1.SecureCRT 1.1SecureCRT支持SSH*&#xff08;SSH1和SSH2&#xff09;&#xff0c;安裝的過程不在贅述 1.2與SecureCRT相關的Linux命令 rz和sz是Linux同windows進行ZModem文件傳輸的命令行工具。 sz命令利用ZModem協議來從Linux服務器傳送文件到本地&#xff0c;一次可以傳送一…

fork、vfork、clone

1. 概念 寫時復制技術最初產生于Unix系統&#xff0c;用于實現一種傻瓜式的進程創建&#xff1a;當發出fork( )系統調用時&#xff0c;內核原樣復制父進程的整個地址空間并把復制的那一份分配給子進程。這種行為是非常耗時的&#xff0c;因為它需要&#xff1a; 為子進程的頁…

Linux02進程內存管理

1.進程地址空間 1.1程序的結構與進程的結構 [rootlocalhost demo]# size testtext data bss dec hex filename 1193 492 16 1701 6a5 test 一個可執行程序包含三個部分&#xff1a; 代碼段&#xff1a;主要存放指令&#xff0c;操作以及只讀的常量數據例…

epoll

開發高性能網絡程序時&#xff0c;windows開發者們言必稱iocp&#xff0c;linux開發者們則言必稱epoll。大家都明白epoll是一種IO多路復用技術&#xff0c;可以非常高效的處理數以百萬計的socket句柄&#xff0c;比起以前的select和poll效率高大發了。我們用起epoll來都感覺挺爽…

劍指offer目錄

序號題目1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

基于升序鏈表的定時器

#ifndef LST_TIMER#define LST_TIMER#include <time.h>#define BUFFER_SIZE 64class util_timer;//用戶數據結構&#xff1a;客戶端地址、客戶端的socket、socket文件描述符、讀緩存和定時器struct client_data{sockaddr_in address;int sockfd;char buf[ BUFFER_SIZE ];…

SIGCHLD信號使用和注意事項

1.SIGCHLD簡介 SIGCHILD是指在一個進程終止或者停止時&#xff0c;將SIGCHILD信號發送給其父進程&#xff0c;按照系統默認將忽略此信號&#xff0c;如果父進程希望被告知其子系統的這種狀態&#xff0c;則應捕捉此信號。注意&#xff1a;SIGCLD信號與其長得非常相似。SIGCLD是…

08-圖7 公路村村通 (30 分

現有村落間道路的統計數據表中&#xff0c;列出了有可能建設成標準公路的若干條道路的成本&#xff0c;求使每個村落都有公路連通所需要的最低成本。 輸入格式: 輸入數據包括城鎮數目正整數N&#xff08;≤&#xff09;和候選道路數目M&#xff08;≤&#xff09;&#xff1b;隨…

【Leetcode】33. 搜索旋轉排序數組

假設按照升序排序的數組在預先未知的某個點上進行了旋轉。 ( 例如&#xff0c;數組 [0,1,2,4,5,6,7] 可能變為 [4,5,6,7,0,1,2] )。 搜索一個給定的目標值&#xff0c;如果數組中存在這個目標值&#xff0c;則返回它的索引&#xff0c;否則返回 -1 。 你可以假設數組中不存在重…

08-圖9 關鍵活動 (30 分

假定一個工程項目由一組子任務構成&#xff0c;子任務之間有的可以并行執行&#xff0c;有的必須在完成了其它一些子任務后才能執行。“任務調度”包括一組子任務、以及每個子任務可以執行所依賴的子任務集。 比如完成一個專業的所有課程學習和畢業設計可以看成一個本科生要完成…

【Leetocde | 10 】54. 螺旋矩陣

解題代碼&#xff1a; class Solution { public:vector<int> spiralOrder(vector<vector<int>>& matrix) {if (matrix.empty() || matrix[0].empty()) return {};int m matrix.size(), n matrix[0].size();vector<int> res;int up 0, down m …

09-排序1 排序 (25 分)

給定N個&#xff08;長整型范圍內的&#xff09;整數&#xff0c;要求輸出從小到大排序后的結果。 本題旨在測試各種不同的排序算法在各種數據情況下的表現。各組測試數據特點如下&#xff1a; 數據1&#xff1a;只有1個元素&#xff1b; 數據2&#xff1a;11個不相同的整數…