Reputation: 781
I was solving the sleeping barber problem as a part of my school assignment. It works fine when I run it with GDB, but gets stuck if I run it from the command line. This is the code:
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
#define MAX 5
int nr_clients, open;
sem_t sem_open1, sem_clients, sem_chair, sem_number;
void *Barber(){
sem_wait(&sem_open1);
printf("Barber: Opening the shop\n");
open = 1;
sem_post(&sem_open1);
while(1){
printf("Barber: Sleeping while there is no clients\n");
sem_wait(&sem_clients);
sem_wait(&sem_number);
if(nr_clients > 0){
sem_post(&sem_number);
printf("Barber: starting to work on a client\n");
sem_post(&sem_chair);
sleep(1);
sem_wait(&sem_number);
printf("Barber: Client finished\n");
nr_clients--;
sem_post(&sem_number);
} else {
printf("Barber: Closing the shop\n");
break;
}
}
}
void *Client(void *x){
int i = *((int*)x);
printf("%8sClient(%d): I want a haircut\n", "", i);
sem_wait(&sem_open1);
sem_wait(&sem_number);
if(open == 1 && nr_clients < MAX){
sem_post(&sem_open1);
printf("%8sClient(%d): entering the shop\n", "", i);
nr_clients++;
sem_post(&sem_number);
sem_post(&sem_clients);
sem_wait(&sem_chair);
printf("%8sClient(%d): barber is working on me\n", "", i);
} else {
printf("No more room\n");
}
}
int main(int argc, char const *argv[])
{
if(sem_init(&sem_open1,0,1) == -1 || sem_init(&sem_clients,0,0) == -1
|| sem_init(&sem_chair,0,0) == -1 || sem_init(&sem_number,0,1) == -1){
printf("ERROR!\n");
return 1;
}
int nr_threads = 5+1;
pthread_t thr_id[nr_threads];
if(pthread_create(&thr_id[0], NULL, Barber, NULL) != 0) {
printf("ERROR!\n");
exit(1);
}
int numbers[nr_threads-1];
for (int i = 0; i < nr_threads-1; ++i)
{
numbers[i] = i;
}
for (int i = 1; i < nr_threads; ++i)
{
if(pthread_create(&thr_id[i], NULL, Client, &numbers[i-1]) != 0){
printf("ERROR!\n");
exit(1);
}
}
sleep(10);
sem_wait(&sem_open1);
open = 0;
sem_post(&sem_open1);
sem_post(&sem_clients);
for (int i = 0; i < nr_threads; ++i)
{
pthread_join(thr_id[i], NULL);
}
}
I compile it like this:
gcc -g sleeping_barber.c -o barber -lpthread
And then just start it in the command line. Command line output:
Client(4): I want a haircut
No more room
Client(3): I want a haircut
Client(2): I want a haircut
Client(1): I want a haircut
Client(0): I want a haircut
^C
It just gets stuck there.
In GDB I run it like this:
(gdb) file barber
Reading symbols from barber...done.
(gdb) r
Starting program: /home/marko/Desktop/barber
GDB output:
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff77f0700 (LWP 2808)]
Barber: Opening the shop
Barber: Sleeping while there is no clients
[New Thread 0x7ffff6fef700 (LWP 2809)]
Client(0): I want a haircut
Client(0): entering the shop
Barber: starting to work on a client
Client(0): barber is working on me
[New Thread 0x7ffff67ee700 (LWP 2810)]
[Thread 0x7ffff6fef700 (LWP 2809) exited]
Client(1): I want a haircut
Client(1): entering the shop
[New Thread 0x7ffff5fed700 (LWP 2811)]
Client(2): I want a haircut
Client(2): entering the shop
[New Thread 0x7ffff57ec700 (LWP 2812)]
Client(3): I want a haircut
Client(3): entering the shop
[New Thread 0x7ffff4feb700 (LWP 2813)]
Client(4): I want a haircut
Client(4): entering the shop
Barber: Client finished
Barber: Sleeping while there is no clients
Barber: starting to work on a client
Client(1): barber is working on me
[Thread 0x7ffff67ee700 (LWP 2810) exited]
Barber: Client finished
Barber: Sleeping while there is no clients
Barber: starting to work on a client
Client(2): barber is working on me
[Thread 0x7ffff5fed700 (LWP 2811) exited]
Barber: Client finished
Barber: Sleeping while there is no clients
Barber: starting to work on a client
Client(3): barber is working on me
[Thread 0x7ffff57ec700 (LWP 2812) exited]
Barber: Client finished
Barber: Sleeping while there is no clients
Barber: starting to work on a client
Client(4): barber is working on me
[Thread 0x7ffff4feb700 (LWP 2813) exited]
Barber: Client finished
Barber: Sleeping while there is no clients
Barber: Closing the shop
[Thread 0x7ffff77f0700 (LWP 2808) exited]
[Inferior 1 (process 2804) exited normally]
Works as described in our assignment.
INFO:
OS -> xubuntu-16.04.1
DEBUGGER -> GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1
Upvotes: 0
Views: 1602
Reputation: 12404
You have multiple problems in your code.
If a client cannot get into the Barber's shop, you never release the semaphores sem_open1
and sem_client
again.
This is the reason why your threads are obviously blocked waiting for sem_open1. You can deduct this because there is not more output after "I want a haircut".
But if we start at the beginning, we see that open
must be 0 when your first thread enters the shop because your condition if(open == 1 && nr_clients < MAX)
is false.
As no one incremented nr_clients
yet, it must be the open
part.
Furthermore you might just look at your output: The Barber didn't yet open the shop. You might add some logic to try again if the shop is closed at first attempt.
The reason for your problem is that you assume a certain order in which your threads are executed. As you can easily see by the thread number in your output, it is not what you expected. You simply cannot rely on any order.
To ensure that your shop is opened you need to give the Barber's thread a chance to run before you start the other threads. Add some sleep()
after creating your Barber.
Finally... With what I have written you might come to the conclusion that it's all about timing. And timing can be very much different if you run your program in a debugger or without a debugger.
Upvotes: 3