Problem description
On a round table sat 5 philosophers, and each of the two philosophers placed a chopstick between the tables, the middle of which was a bowl of rice, as shown in 2-10. Philosophers devote their whole life to thinking and eating, and philosophers do not affect others when they think. Only when the philosopher was hungry did he attempt to pick up the left and right two chopsticks (one by one). If the chopsticks are already in the hands of others, wait. The hungry philosopher can only get two chopsticks at the same time to start eating, when the meal is finished, put down the chopsticks to continue to think.
Problem analysis
1) Relationship analysis. The 5 philosophers were mutually exclusive with the right and left neighbors ' access to their intermediate chopsticks.
2) Arrange ideas. Obviously there are five processes here. The key is how to get a philosopher to get around two chopsticks without causing deadlocks or starvation. So there are two solutions, one is to get them to take two chopsticks at the same time, and the other is to make rules for the actions of each philosopher to avoid starvation or deadlock.
A total of 5 philosophers, numbered 0 ~, 5 chopsticks numbered is also 0 ~, No. 0 Philosopher's right hand chopstick number No. 0, counter-clockwise increase, philosopher's number is also counterclockwise increase so: No. 0 philosopher corresponds to: 4th and 1th chopsticks. The philosopher 1th corresponds to: No. 0 and 2nd chopsticks. The philosopher 2nd corresponds to: Chopsticks 1th and 3rd. Philosopher 3rd corresponds to: 2nd and 4th chopsticks. The philosopher 4th corresponds to: 3rd and No. 0 chopsticks. So there is a macro definition:
#define Left (phi_id) (phi_id+n-1)%N#define Right (phi_id) (phi_id+1)%N5
5 chopsticks correspond to 5 mutual exclusion locks, so:
pthread_mutex_t Forks[n]={pthread_mutex_initializer};
The actions the philosopher thread needs to perform are:
voidTake_forks (intID) { //get chopsticks on both sides of the leftprintf"pil[%d], left[%d], right[%d]\n", ID, left (ID), right (ID)); Pthread_mutex_lock (&Forks[left (ID)]); Pthread_mutex_lock (&forks[right (ID)]); //printf ("philosopher[%d] take_forks...\n", id);}voidPut_down_forks (intID) {printf ("philosopher[%d] is put_down_forks...\n", id); Pthread_mutex_unlock (&Forks[left (ID)]); Pthread_mutex_unlock (&forks[right (ID)]);}void* Philosopher_work (void*Arg) { intID = * (int*) Arg; printf ("philosopher init [%d] \ n", id); while(1) {thinking (ID); Take_forks (ID); Eating (ID); Put_down_forks (ID); }}
The algorithm has the following problems: When five philosophers want to eat, pick up their left chopsticks
Pthread_mutex_unlock (&Forks[left (ID)]);)
Chopsticks have been taken out, and when they want to take the right chopsticks again (execute
Pthread_mutex_unlock (&forks[right (ID)]);
was blocked, and there was a deadlock.
In order to prevent the occurrence of deadlocks, it is possible to impose some restrictions on the philosopher's process, numbering philosophers sequentially, and allowing him to grab chopsticks when the chopsticks are available on both sides of a philosopher's side.
void* philosopher_work (void *arg) { int id = * (int*) arg; printf ("philosopher init [%d] \ n", id) ; while (1) { thinking (ID); Pthread_mutex_lock (&mutex); Take_forks (ID); Pthread_mutex_unlock (&mutex); Eating (ID); Put_down_forks (ID);} }
One problem with this code is that only one philosopher can take chopsticks at a time of unification, which is less efficient.
The full source code is as follows:
/************* * Every philosopher is on while loop:thinking, Take_forks, eating-put_down_for KS-thingking * * For possible deadlock problems, we use a solution here, that is only when the philosophy of the left and right two chopsticks are in the available state, * Only allow him to pick up chopsticks. This prevents them from picking up chopsticks at the same time to dine, leading to deadlocks. * If the 2nd philosopher is at dinner then number 1th and 3rd must be thinking. * * * * * ************/#include<stdio.h>#include<stdlib.h>#include<pthread.h>#include<semaphore.h>#include<unistd.h>#defineN 5//Five philosopher#defineT_eat 5#defineT_think 5#defineLeft (phi_id) (phi_id+n-1)%N#defineRight (phi_id) (phi_id+1)%Nenum{Think, hungry, eat}phi_state[n];p thread_mutex_t Mutex=pthread_mutex_initializer;pthread_mutex_t Forks[n]={Pthread_mutex_initializer};voidThinking (intID) {Sleep (T_think); printf ("philosopher[%d] is thinking...\n", id);}voidEatingintID) {Sleep (t_eat); printf ("philosopher[%d] is eating...\n", id);}voidTake_forks (intID) { //get chopsticks on both sides of the leftprintf"pil[%d], left[%d], right[%d]\n", ID, left (ID), right (ID)); Pthread_mutex_lock (&Forks[left (ID)]); Pthread_mutex_lock (&forks[right (ID)]); //printf ("philosopher[%d] take_forks...\n", id);}voidPut_down_forks (intID) {printf ("philosopher[%d] is put_down_forks...\n", id); Pthread_mutex_unlock (&Forks[left (ID)]); Pthread_mutex_unlock (&forks[right (ID)]);}void* Philosopher_work (void*Arg) { intID = * (int*) Arg; printf ("philosopher init [%d] \ n", id); while(1) {thinking (ID); Pthread_mutex_lock (&mutex); Take_forks (ID); Pthread_mutex_unlock (&mutex); Eating (ID); Put_down_forks (ID); }}intMain () {pthread_t phitid[n]; inti; interr; int*id= (int*) malloc (sizeof(int)*N); for(i=0; i < N; ++i) { //printf ("I ==%d\n", i);Id[i] =i; Err= Pthread_create (&phitid[i], NULL, Philosopher_work, (void*) (&id[i]));//The thread ID generated by this scenario is 0,1,2,3,4 if(Err! =0) printf ("can ' t create process for reader"); } while(1); return 0;}
The question of the Philosopher's meal