1. 程式人生 > >哲學家問題 pthread訊號量實現

哲學家問題 pthread訊號量實現

#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<semaphore.h>
#define false 0
#define true 1
long  thread;
long  count;
void * SeqEat(void * rank);
void * NoOrder(void * rank);
void * NoDeadLock(void *rank);
int main(int argc,char * argv[]){
    pthread_t * thread_handles;
    count=strtol(argv[2]+1,NULL,10);
    printf("count is :%lld\n",count);

    void* (*op)(void *);//op is a pointer to a function,which could change to different functions according to the input argument
    if(strcmp(argv[1],"-semaphore")==0) {op=SeqEat;init_SeqEat();}//if argument is "_semaphore",op points to the function SeqEat() and execute the init function,which initialize some variables
    else if(strcmp(argv[1],"-noorder")==0) {op=NoOrder;init_NoOrder();}
    else if(strcmp(argv[1],"-nodeadlock")==0) {op=NoDeadLock;init_NoDeadLock();}
    else {
        puts("Wrong argument");//if the first argument is not identified ,then give an error message and return
        return 0;
    }
    thread_handles =  malloc(count*sizeof (pthread_t));
    for(thread=0;thread<count;thread++){
        pthread_create(&thread_handles[thread],NULL,op,(void *)thread);// the thread uses function where op points to    
    }
    for(thread=0;thread<count;thread++){
        pthread_join(thread_handles[thread],NULL);
    }
    
    free(thread_handles);
    return 0;
}

sem_t *canEat;//canEat point to an array of semaphore ,where canEat[i] means ith person can eat or not,he can not eat until canEat[i] is 1
void init_SeqEat(){
    canEat = malloc(count*sizeof (sem_t));
    sem_init(&canEat[0],0,1);//the 0th person eat first
    for(int i=1;i<count;i++) sem_init(&canEat[i],0,0);//ohters now can't eat
}
void * SeqEat(void *r){
    long rank=(long)r;
    sem_wait(&canEat[rank]);//wait until this person can eat

    printf("%lld is eating\n",rank);//he is eating...

    sem_post(&canEat[(rank+1)%count]);//after he ate,he must allow the person hehind him could eat
    return NULL;
}

sem_t *chop;//chop point to an array of semaphore ,where chop[i] means ith chopstick can, be used or not,it can not be used until  chop[i] is 1
void init_NoOrder(){
    chop = malloc(count*sizeof(sem_t));
    for(int i=0;i<count;i++) sem_init(&chop[i],0,1);//every chopsticks is unused,so set semaphore  to 1
}
void * NoOrder(void * r){
    long rank=(long)r;
    sem_wait(&chop[rank]);//get the left chop first
    printf("%lld get the left chop\n",rank);

    sem_wait(&chop[(rank+count-1)%count]);//get the left chop first
    printf("%lld get the right chop\n",rank);

    printf("%lld is eating\n",rank);//he is eating...
    sem_post(&chop[(rank+count-1)%count]);//release the left chop first
    printf("%lld release the  right chop\n",rank);
    sem_post(&chop[rank]);//release the left chop first
    printf("%lld release the  left chop\n",rank);
}
sem_t *max_person;//max_person is a semaphore pointer ,which is set count-1 first,becase  I set a constrain that no more than count-1 people could have chopsticks,which could be justfied that deadlock will never happen when under this constrain
void init_NoDeadLock(){
    max_person=malloc(1*sizeof(sem_t));
    sem_init(max_person,0,count-1);//set max_person to  count-1
    chop = malloc (count*sizeof (sem_t));
    for(int i=0;i<count;i++) sem_init(&chop[i],0,1);//every chopsticks is unused,so set semaphore  to 1
}
void * NoDeadLock(void *r){
    long rank=(long)r;
    long L=rank;//L means the left chopstick
    long R=(rank+count-1)%count;//R means the right chopstick
    sem_wait(max_person);//if max_person is count-1 ,then wait
    sem_wait(&chop[L]);//try to get left chopstick
    sem_wait(&chop[R]);//try to get right chopstick
    printf("%d is eating\n",rank);
    printf("%d end eating\n",rank);
    sem_post(&chop[L]);//release the left chopstick
    sem_post(&chop[R]);//release the right chopstick
    sem_post(max_person);//add max_persoon

}