Dixit Singla
Dixit Singla

Reputation: 293

Semaphore not working properly?

I have just started learning threads and semaphores. I have created a simple program in C but its not working as expected. Please look at the code and tell me where I am wrong?

Thanks in advance.

I am using Ubuntu 14.04.

Commands I am using

gcc -o foo th.c -lpthread

./foo

th.c is the name of my c file

on execution every time the program should output:

Thread 1

Thread 2

Hello threads!

But I am getting most of the times

Thread 2

Thread 1

Code:

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

void myFun1(void *ptr);
void myFun2(void *ptr);

char buf[24];
sem_t mutex;

int main(){

    pthread_t t1;
    pthread_t t2;

    char *msg1 = "Thread 1";
    char *msg2 = "Thread 2";

    sem_init(&mutex, 0, 1);

    printf("mutex 00 %d \n", mutex);    
    pthread_create(&t1, NULL, (void *) &myFun1, (void *) msg1);
    pthread_create(&t2, NULL, (void *) &myFun2, (void *) msg2);

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    sem_destroy(&mutex);

    return 0;
}

void myFun1 (void *ptr) {

    char *msg = (char *)ptr;
    printf("%s\n", msg);

    sem_wait(&mutex);
    sprintf(buf, "%s", "Hello Threads!");
    sem_post(&mutex);

    pthread_exit(0);
}

void myFun2(void *ptr) {

    char *msg = (char *)ptr;
    printf("%s\n", msg);

    sem_wait(&mutex);
    printf("%s\n", buf);
    sem_post(&mutex);

    pthread_exit(0);
}

Upvotes: 0

Views: 1169

Answers (1)

caf
caf

Reputation: 239011

Your expectation is wrong. Your program does not include any synchronisation to make the t1 thread execute before the t2 thread (or vice-versa), so either ordering is possible.

In the case where t2 acquires the semaphore first, buf will still be an empty string and that is what will print.

What you need is for t2 to wait until t1 has filled the buffer. You can do this by initialising the semaphore to 0, and only posting the semaphore after buf has been written to. In main():

sem_init(&mutex, 0, 0);

In myFun1:

void myFun1 (void *ptr) {

    char *msg = (char *)ptr;
    printf("%s\n", msg);

    sprintf(buf, "%s", "Hello Threads!");
    sem_post(&mutex);

    pthread_exit(0);
}

In myFun2:

void myFun2(void *ptr) {

    char *msg = (char *)ptr;
    printf("%s\n", msg);

    sem_wait(&mutex);
    printf("%s\n", buf);

    pthread_exit(0);
}

Now t2 will only try to print buf after it has been initialised, regardless of whether t2 or t1 runs first.

Upvotes: 1

Related Questions