First of all, what is a philosopher's meal problem, which is a classic synchronization problem in the operating system course,
The problem is as follows: For example, there are 6 philosophers and 6 chopsticks (the blue part is the philosopher, the purple Bar is the chopsticks), they were 0~5! If a philosopher wants to eat, he must pick up the two chopsticks on the left and right side at the same time to dine! After the philosopher's meal, he put down the two chopsticks he picked up in his hand! So other philosophers can eat these chopsticks! Note that the number of philosophers must be an even number!
OK, so there may be a deadlock problem, such as the number No. 0 philosopher took No. 0 chopsticks, 1th philosopher took the number 1th chopsticks! So the end result is that each philosopher only took 1 chopsticks, everyone can not eat, at the same time can not put down the chopsticks! This creates a deadlock!
So how does the deadlock work? It's simple, according to the Philosopher's number! If it is an even number of philosophers, then take the right hand side chopsticks (small number), and then take the left hand side of the chopsticks (large number). And the philosopher of the odd number is just the opposite! In this way, it will not appear that every philosopher took only one chopsticks!
How is the specific program implemented? The code is as follows:
1 /*description, this procedure is to simulate the realization of the problem of the philosopher dining, a total of 6 philosophers and 6 chopsticks2 */3#include <stdio.h>4#include <string.h>5#include <stdlib.h>6#include <unistd.h>7#include <errno.h>8#include <pthread.h>9 Ten #defineB_size 4096 One #defineNum_p 6 A -typedefstructPhi - { thepthread_mutex_t Chopsticks[num_p];//Five Chopsticks - intNum//the Philosopher's number -pthread_mutex_t Num_lock;//the lock of the philosopher number -}phi,*Pphi; + void* TFUNC (void*Arg) - { +Pphi SP =(Pphi) arg; A intPhi_num; at intNext_num; - - /*read the Philosopher's number*/ -Phi_num = sp->num; -Pthread_mutex_unlock (&sp->num_lock); -printf"no.%d philosopher has comed\n", phi_num); in /*Next Chopsticks*/ -next_num= phi_num+1>=num_p?phi_num+1-num_p:phi_num+1; to +Sleep5);//All Threads Unified Sleep 5S, to wait for other threads to finish creating - the if(phi_num%2==1)//The odd number takes the big first, then takes the small * { $Pthread_mutex_lock (& (sp->Chopsticks[next_num]));Panax Notoginseng //printf ("no.%d philosopher Lock the no.%d chopstick\n", phi_num,next_num); -Pthread_mutex_lock (& (sp->Chopsticks[phi_num])); the //printf ("no.%d philosopher Lock the no.%d chopstick\n", phi_num,phi_num); + Aprintf"no.%d philosopher has eated!\n", phi_num); the +Pthread_mutex_unlock (& (sp->Chopsticks[next_num])); - //printf ("no.%d philosopher unlock the no.%d chopstick\n", phi_num,next_num); $Pthread_mutex_unlock (& (sp->Chopsticks[phi_num])); $ //printf ("no.%d philosopher unlock the no.%d chopstick\n", phi_num,phi_num); - } - Else //I'll take the small number first, then take the big. the { -Pthread_mutex_lock (& (sp->Chopsticks[phi_num]));Wuyi //printf ("no.%d philosopher Lock the no.%d chopstick\n", phi_num,phi_num); thePthread_mutex_lock (& (sp->Chopsticks[next_num])); - //printf ("no.%d philosopher Lock the no.%d chopstick\n", phi_num,next_num); Wu -printf"no.%d philosopher has eated!\n", phi_num); About $Pthread_mutex_unlock (& (sp->Chopsticks[phi_num])); - //printf ("no.%d philosopher unlock the no.%d chopstick\n", phi_num,phi_num); -Pthread_mutex_unlock (& (sp->Chopsticks[next_num])); - //printf ("no.%d philosopher unlock the no.%d chopstick\n", phi_num,next_num); A } + the return(void*)0; - } $ intMainintargcChar*argv[]) the { the interr; the pthread_t tid[num_p]; the CharBuf_err[b_size];//used to save error messages - void*retv;//The return value of the child thread in Phi phis; the the for(intloop=0; loop<num_p;loop++) About { the /*set the Philosopher's number*/ thePthread_mutex_lock (&phis.num_lock); thePhis.num =Loop; + - /*Create a child thread as a philosopher*/ theErr = Pthread_create (&tid[loop],NULL,tfunc,&phis);Bayi if(0!=err) the { thememset (Buf_err,0, b_size); -sprintf (Buf_err,"[create]:%s\n", Strerror (err)); - fputs (buf_err,stderr); the exit (exit_failure); the } the } the - for(intloop=0; loop<num_p;loop++) the { theErr = Pthread_join (tid[loop],&Retv); the if(0!=err)94 { thememset (Buf_err,0, b_size); thesprintf (Buf_err,"[join]:%s\n", Strerror (err)); the fputs (buf_err,stderr);98 exit (exit_failure); About } - 101printf"Main:thread Return the value:%d\n",(int) Retv);102 }103 104 return 0; the}
In the above program, I created a struct body phi! Among them, chopsticks is a defined five mutex, used to represent 5 chopsticks! The NUM variable is used to denote the philosopher's number, and the Num_lock represents a lock on the philosopher's number, which is why this is set, and then it is!
First of all, the main program is to create num_p sub-threads to represent so many philosophers! In sub-threads, it is necessary to choose different ways to take chopsticks according to the parity of the Philosopher's numbers! This needs to pass a philosopher number to this sub-thread! By what pass, is the NUM variable in the PHI struct! Here we come across a problem! That is, if NUM is set in the main thread, and then the child thread is created, but the child thread has not yet read the value of NUM, the main thread has already started the next cycle, then it is likely that the NUM value that the child thread reads is not what we want it to read! So here is the use of Num_lock this lock, the main thread to write the value of NUM, the Num_lock this lock to lock, and then the sub-thread read Num's after the Num_lock this lock to unlock, and then the main thread to the next cycle! This ensures that the number that the sub-thread reads is the number we want to pass to him!
In the sub-thread, I first output a sentence "no.%d philosopher has comed\n", indicating that a child thread has been created! Then let this thread sleep 5S, waiting for other child threads to be created (this is not really needed, but I feel like the philosophers are basically starting to eat together ...). ^_~)! Then, according to the idea above, the philosopher of the number number first took the right hand side chopsticks, then took the left hand side chopsticks, the odd number philosopher is opposite! So you can avoid the deadlock!
Another problem is that this variable, which I define in the Next_num, is used to denote the value of the next chopstick that the philosopher takes, because the next chopstick of the philosopher with the largest number is the No. 0 chopstick, so I use an if judgment to distinguish it!
The results of the final program run as follows:
OK, that's it! Hope to be able to learn the operating system of friends to generate some help!
Using the pthread_mutex_t type of Linux to realize the dining problem of philosophers