Search code examples
cmultithreadingmutexcritical-section

C - unable to pass thread into critical section with specific ticket number


I'm trying to implement ticket algorithm. I have X threads there and I want to synchronize their entrance into critical section by ticket numbers, thread with ticket number 0 will enter critical section first, with number 1 will enter as a second etc.

I implemented this critical section issue in while loop with if condition inside to check thread ticket number. But I'd love to avoid using active waiting - testing condition in loop.

So I'm thinking if there is some another way with mutex containing condition for example, like thread locked by mutex and waiting for some global variable to have the same value as thred's ticket number.

This is my function with active waiting:

void *threadInitial(void *void_ptr){

    // my thread structure with thread id and ticket number   
    Thread *threadActual = void_ptr;
    // get ticket number
    sem_wait(&semaphoreTicketGet);
    threadActual->threadTicket = getticket();
    sem_post(&semaphoreTicketGet);

    while(1){
      // check if this thread is allowed to enter critical section
      if(threadActual->threadTicket != enterTicketNumber)    continue;

      sem_wait(&semaphoreTicketPrint);
      // critical section
      enterTicketNumber++;
      sem_post(&semaphoreTicketPrint);
      break;
   }
   return NULL;
}

And this function is called like this:

pthread_create(&threadsArr[count].threadPointer, NULL, threadInitial, &threadsArr[count])

Don't you have any idea how to solve it?


Solution

  • You can use condition variables:

    "Condition variables provide yet another way for threads to synchronize. While mutexes implement synchronization by controlling thread access to data, condition variables allow threads to synchronize based upon the actual value of data."

    https://computing.llnl.gov/tutorials/pthreads/#ConditionVariables

    //global variable
    pthread_cond_t      cond  = PTHREAD_COND_INITIALIZER;
    
    void *threadInitial(void *void_ptr){
    
      // my thread structure with thread id and ticket number
      Thread *threadActual = void_ptr;
    
      // get ticket number
      sem_wait(&semaphoreTicketGet);
      threadActual->threadTicket = getticket();
      sem_post(&semaphoreTicketGet);
    
      // wait for my turn
      sem_wait(&semaphoreTicketPrint);
      while (threadActual->threadTicket != enterTicketNumber)
            pthread_cond_wait(&cond, &semaphoreTicketPrint);
      enterTicketNumber++;
      pthread_cond_signal(&cond);
      sem_post(&semaphoreTicketPrint);
    
      return NULL;
    

    }