Peterson's Algorithm to avoid race condition between threads

3.3k views Asked by At

Details:

I am implementing Peterson's Algorithm(below) to avoid race condition. The way I want to do it, is to declare a global integer variable, and create threads one and two. Whenever the thread one had access to the global variable it should print a and add one to the global variable counter. When the thread two have access to this global variable it should print b and add one to the global variable counter. This should continue until the global variable reaches a certain number(let's say 10). After that I want the thread(which ever of the two threads that makes the last addition to the global variable) to reset the global variable to 1 and both threads should exit. The code that I have implemented so far kinda does the job,it avoids race condition, but I can't exit both threads when counter reaches limit.

Question:

  • How can I quit both threads when the counter reaches a specific limit.

  • Whats the proper form of quitting a thread, right now I am using exit(), which I don't think is very efficient.

Peterson's Algorithm

boolean flag [2];
int turn;
void P0()
{
    while (true) {
         flag [0] = true;
         turn = 1;
         while (flag [1] && turn == 1) /* do nothing */;
         /* critical section */;
         flag [0] = false;
         /* remainder */;
    }
}

void P1()
{
     while (true) {
          flag [1] = true;
          turn = 0;
          while (flag [0] && turn == 0) /* do nothing */;
          /* critical section */;
          flag [1] = false;
          /* remainder */
     }
}

 void main()
 {
       flag [0] = false;
       flag [1] = false;
       parbegin (P0, P1);
 }

My Code:

EDIT: I realized that I have to put the if-statement, that is checking for the counter limit value, should be in the critical section(before it changes the flag to false).

#include<stdlib.h>
#include<stdio.h>
#include<pthread.h>


int counter = 0;

int flag[2];
int turn;

void *func1(void *);
void *func2(void *);

int main(int argc,char *argv[]){

    pthread_t thread1,thread2;
    //int rt1,rt2;

    flag[0] = 0;
    flag[1] = 0;

    //rt1 = pthread_create(&thread1,NULL,&func1,"a");
    //rt2 = pthread_create(&thread2,NULL,&func2,"c");
    pthread_create(&thread1,NULL,&func1,"a");
    pthread_create(&thread2,NULL,&func2,"b");

    pthread_join(thread1,NULL);
    pthread_join(thread2,NULL);

    return 0;
}// End of main function


void *func1(void *message){


    while(1){
        flag[0] = 1;
        turn = 1;
        while(flag[1] && turn == 1);
        printf("%s %d\n",(char *)message,counter);
        counter++;
        flag[0] = 0;        

        if(counter == 10){
            counter = 1;
            printf("exited at func1, with counter %d\n",counter);
            exit(0);
        }   
    }
    return 0;
}

void *func2(void *message){

    while(1){
        flag[1] = 1;
        turn = 0;
        while(flag[0] && turn == 0);
        printf("%s %d\n",(char *)message,counter);
        counter++;
        flag[1] = 0;

        if(counter == 10){
            counter = 1;
            printf("exited at func2, with counter %d\n",counter);
            exit(0);
        }
    }
    return 0;
}
1

There are 1 answers

4
AudioBubble On BEST ANSWER

Obviously, when one thread resets the global counter, the other thread may never see the global counter reaching e.g.10, so it will never quit. What if you simply don't reset the global counter, and let it thread quit whenever it finds the global counter e.g. 10? If you really want to reset the counter, you do that in the parent (main) thread (which is also where you define the global counter).

As for quitting a thread, you can either simply return from the primary thread function (this will end the thread by itself), call pthread_exit from within the thread, or you can use phtread_cancel from the main function.