Giorgi Cercvadze Giorgi Cercvadze - 17 days ago 4
C Question

Threads work inappropriately

I'm writing this code in c

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

typedef struct
{
int customerID;
int ticketNumber;
sem_t * freeCashiers;
sem_t Cashiers[2];
}Customer;

int firstIsFree = 1;
int secondIsFree = 1;

void * buyTheTickets(void * data)
{
Customer * currentCustomer = (Customer *)data;
int ID = currentCustomer->customerID;

currentCustomer->ticketNumber = rand()%15+1;

sem_wait(currentCustomer->freeCashiers);

sem_wait(&(currentCustomer->Cashiers[0]));

if(firstIsFree)
{
firstIsFree = 0;
printf("First Cashier Sold %d Ticket To %d Customer\n",currentCustomer->ticketNumber,ID);

usleep(1000000);
firstIsFree = 1;

sem_post(&(currentCustomer->Cashiers[0]));
sem_post(currentCustomer->freeCashiers);

return 0;
}

sem_post(&(currentCustomer->Cashiers[0]));

sem_wait(&(currentCustomer->Cashiers[1]));

if(secondIsFree)
{
secondIsFree = 0;
printf("Second Cashier Sold %d Ticket To %d Customer\n",currentCustomer->ticketNumber,ID);

usleep(1000000);
secondIsFree = 1;

sem_post(&(currentCustomer->Cashiers[1]));
sem_post(currentCustomer->freeCashiers);

return 0;
}
sem_post(&(currentCustomer->Cashiers[1]));
}

int main()
{
int numberOfCustomers = 15;
sem_t * numberOfCashiers = (sem_t*)malloc(sizeof(sem_t));
sem_init(numberOfCashiers,0,2);
sem_t first;
sem_t second;
sem_init(&first,0,1);
sem_init(&second,0,1);

for(int i=1;i<=numberOfCustomers;i++)
{
pthread_t * curTh = (pthread_t*)malloc(sizeof(pthread_t));
Customer * curCu = (Customer *)malloc(sizeof(Customer));
curCu->customerID = i;
curCu->freeCashiers = numberOfCashiers;
curCu->Cashiers[0] = first;
curCu->Cashiers[1] = second;
pthread_create(curTh,NULL,buyTheTickets,curCu);
}

pthread_exit(0);
return 0;
}


And it gives output:

First Cashier Sold 14 Ticket To 1 Customer

Second Cashier Sold 2 Ticket To 2 Customer

First Cashier Sold 13 Ticket To 3 Customer

Second Cashier Sold 11 Ticket To 4 Customer

First Cashier Sold 9 Ticket To 5 Customer

Second Cashier Sold 11 Ticket To 6 Customer

First Cashier Sold 2 Ticket To 7 Customer

Second Cashier Sold 13 Ticket To 8 Customer

First Cashier Sold 10 Ticket To 9 Customer

Second Cashier Sold 2 Ticket To 10 Customer

First Cashier Sold 3 Ticket To 11 Customer

Second Cashier Sold 8 Ticket To 12 Customer

First Cashier Sold 6 Ticket To 13 Customer

Second Cashier Sold 5 Ticket To 14 Customer

First Cashier Sold 9 Ticket To 15 Customer


The Question is that if the second thread goes after
sem_wait(&(currentCustomer->Cashiers[0]));
It means
sem_post(&(currentCustomer->Cashiers[0]));
this already happened so firstIsFree is already 1 so why does it print the second printf?

Jay Jay
Answer

Below issue is present in your code which could lead to undefined behaviour. Please correct it and try the execution again:

In your main function, you are using local variables for semaphores first and second and your main function seems to exit without waiting for the threads to exit. You need to have pthread_join calls in your main function.