A detailed explanation of the philosopher's dining problem

2.23 Philosopher’s Dining Problem

Proposed by Dijkstra in 1965

Problem Description

  • 5 philosophers sitting around a round table
  • 5 forks placed at intervals
  • Philosopher acts as thinking or eating
  • Philosophers must use both forks at the same time
  • Put the fork back into place while thinking
  • Two philosophers don’t use the same fork
  • Try to avoid deadlock and starvation

As shown
Insert picture description here


Option one takes the left fork

Go get the fork on the left, deadlock

semaphore fork[5] = {
    
    1, 1, 1, 1, 1};

void main()
{
    
    
        cobegin {
    
    philosopher(0); 
				 philosopher(1); 
				 philosopher(2);
				 philosopher(3); 	
				 philosopher(4);
				}coend;
}

void philosopher(int i)
{
    
    
         while(true) {
    
    
                think;                      //思考
                wait(fork[i]);           //拿起左边的叉子
                wait(fork[(i+1)%5]);     //拿起右边的叉子
                 eat();
                signal(fork[i]);         //放回左边的叉子
                signal(fork[(i+1)%5]);   //放回右边的叉子
          }
}

Option II

Request to take two forks at the same time, if occupied, wait for random events to request again, possibly livelock

semaphore fork[5] = {
    
    1, 1, 1, 1, 1};

void main()
{
    
    
        cobegin {
    
    philosopher(0); 
				 philosopher(1); 
				 philosopher(2);
				 philosopher(3); 	
				 philosopher(4);
				}coend;
}

void philosopher(int i)
{
    
    
    while(true) {
    
    
    think;              //思考
    wait(fork[i]);          //拿起左边的叉子
    timeout(wait(fork[(i+1)%5], [0, T]) //若右边的叉子被占用,则放下左边叉,等待一段随机时间后再拿                           
    eat();                                                               
    signal(fork[i]);    	//放回左边的叉子
    signal(fork[(i+1)%5]);  //放回右边的叉子
          }
}

Scheme three resource classification

Assign a partial order or hierarchy relationship to resources (here, forks), and agree that all resources are acquired in this order and released in reverse order, and it is guaranteed that there will not be two unrelated resources at the same time Needed by the same job

① Number the fork
  • Before eating, take the fork with the lower number first and then the fork with the higher number
  • After the meal, put down the fork with the higher number first, and then the fork with the lower number
semaphore fork[5] = {
    
    1, 1, 1, 1, 1};
void main()
{
    
    
        cobegin {
    
    philosopher(0); 
				 philosopher(1); 
				 philosopher(2);
				 philosopher(3); 	
				 philosopher(4);
				}coend;
}
void philosopher(int i)
{
    
    
   while(true) {
    
    
      think();  //思考
      if (i  !=  4) {
    
    
           wait(fork[i]); wait(fork[(i+1)%5]);} //先左后右
      else {
    
    
           wait(fork[(i+1)%5]); wait(fork[i]);} //先右后左
      eat(); 
      if (i  !=  4) {
    
    
           signal(fork[(i+1)%5]); signal(fork[i]);} //先右后左
      else {
    
    
           signal(fork[i]); signal(fork[(i+1)%5]);} //先左后右
   }
}
② Number the philosopher
  • The odd-numbered philosopher must first take the fork on the left
  • The even-numbered philosopher must first take the fork on the right
semaphore fork[5] = {
    
    1, 1, 1, 1, 1};
void main()
{
    
    
        cobegin {
    
    philosopher(0); 
				 philosopher(1); 
				 philosopher(2);
				 philosopher(3); 	
				 philosopher(4);
				}coend;
}

void philosopher(int i)
{
    
    
    while(true) {
    
    
       think();  //思考
       if (i % 2 != 0) {
    
    
           wait(fork[i]); wait(fork[(i+1)%5]);} //先左后右
       else {
    
    
           wait(fork[(i+1)%5]); wait(fork[i]);}
       eat(); 
       signal(fork[(i+1)%5]);                   //先右后左
       signal(fork[i]);   
    }
}

Scheme 4 waiter method

  • Introduce a waiter in a restaurant, the philosopher must get his permission to pick up the fork
  • Up to 4 philosophers are allowed to eat at the same time
semaphore fork[5] = {
    
    1, 1, 1, 1, 1}, room = 4;
void main()
{
    
    
       cobegin {
    
    philosopher(0); 
				 philosopher(1); 
				 philosopher(2);
				 philosopher(3); 	
				 philosopher(4);
				}coend;
}

void philosopher(int i)
{
    
    
         while(true) {
    
    
                think;                          //思考
                wait(room);                     //占据就餐位置
                wait(fork[i]);                  //拿起左边的叉子
                wait(fork[(i+1)%5]);            //拿起右边的叉子
                signal(fork[i]);                //放回左边的叉子
                signal(fork[(i+1)%5]);          //放回右边的叉子
                signal(room);                   //释放就餐位置
          }
}

Extension: And type semaphore set

  • Apply for multiple critical resources required in a primitive, either all of them or none of them are allocated
  • The primitive P of the AND type semaphore set is Swait (Simultaneous Wait), and the primitive V is Ssignal (Simultaneous Signal).
  • Swait(S1, S2, …, Sn)
  • Ssignal(S1, S2, …, Sn)

Management plan

monitor dining controller;
cond ForkReady [5];					/*condition variable for synchronization */
boolean fork[ 5]={
    
     true } ; 		/*availability status of each fork*/

void get_forks (int pid)			/*pid is the philosopher id number */
{
    
    
	int left = pid;
	int right =(+pid)%5;
	/*grant the left fork*/
	if( ! fork [ left])
		cwait(ForkReady [ left] );	/*queue on condition variable */
	fork [ left]= false ;
	/*grant the right fork*/
	if( ! fork [ right] )
		cwait(ForkReady [right] );
	/*queue on condition variable */
	fork [ right] = false;
}

void release_forks ( int pid){
    
    
	int left = pid;
	int right =(++pid)%5;
	/*release the left fork*/
	if( empty (ForkReady [ leftl)	/*no one is waiting for this fork */
		fork [ left] = true;
	else							/*awaken a process waiting on this fork */
		csignal (ForkReady [ left]);
	/*release the right fork*/
	if (empty (ForkReady [right])	/*no one is waiting for this fork*/
		fork [ right]= true;
	else							/*awaken a process waiting on this fork*/
		csignal (ForkReady [right] );
}

void philosopher [ k=0 to 4]		/*the five philosopher clients */
{
    
    
	while (true){
    
    
		<think>;
		get_forks (k);				/*client requests two forks via monitor * /
		<eat spaghetti>;
		release_forks (k);			/*client releases forks via the monitor */
	}
}

Insert picture description here

Guess you like

Origin blog.csdn.net/qq_44722674/article/details/111570483
Recommended