Reputation: 425
I am learning to use semaphores and below is a small scenario which I've tried to implement. Its behaving weird in a way. After sem_wait() gets unblocked first time, its not getting blocked again and keeps on looping, not getting why. Is this the right way or right scenario to use semaphore?
EDIT: I just realized that if I uncomment the sleep after sem_post, it works fine. .Reason being it was repeatedly doing sem_post() before thread could do coin=0 I believe. But is it right to use sleep this way with semaphores. I believe this would be considered a bad practice?
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <semaphore.h>
#define MAX_MSG_LEN 256
sem_t sem1;
sem_t sem2;
int coin=0;
void *thrdFun1(void *arg);
void *thrdFun2(void *arg);
void toggleCase(char *buf, int cnt);
int main()
{
pthread_t thrd1;
char argmsg1[] = "Thread1: Waiting to deliver\n";
int thNum;
int res;
res = sem_init(&sem1, 0,0);
// res = sem_init(&sem2, 0,0);
res = pthread_create(&thrd1, NULL, thrdFun1, argmsg1);
while(1)
{
if (coin==0)
{
printf("no coin: please enter coin\n");
scanf("%d",&coin);
}
else
{
sem_post(&sem1);
// sleep(1);
}
}
return 0;
}
void *thrdFun1(void *arg)
{
while(1)
{
printf("I'm %s\n",(char *)arg);
sem_wait(&sem1);
printf("Delivered...\n");
coin=0;
sleep(1);
}
}
Upvotes: 0
Views: 3427
Reputation: 3107
You realized it right, it is repeatedly doing sem_post()
before thread could do coin=0
when removing all sleep
s.
To solve this you could use second semaphore (you already tried it seems) like below,
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <semaphore.h>
#define MAX_MSG_LEN 256
sem_t sem1;
sem_t sem2;
int coin=0;
void *thrdFun1(void *arg);
void *thrdFun2(void *arg);
void toggleCase(char *buf, int cnt);
int main()
{
pthread_t thrd1;
char argmsg1[] = "Thread1: Waiting to deliver\n";
int thNum;
int res;
res = sem_init(&sem1, 0,0);
res = sem_init(&sem2, 0,0);
res = pthread_create(&thrd1, NULL, thrdFun1, argmsg1);
while(1)
{
if (coin==0)
{
printf("no coin: please enter coin\n");
scanf("%d",&coin);
}
else
{
sem_post(&sem1); // Coin is spun
sem_wait(&sem2); // Wait till it is caught
}
}
return 0;
}
void *thrdFun1(void *arg)
{
while(1)
{
printf("I'm %s\n",(char *)arg);
sem_wait(&sem1); // Wait to spin the coin
coin=0;
sem_post(&sem2); // inform as caught
printf("Delivered...\n");
}
}
Upvotes: 1
Reputation: 241
there is a chance that "Thread1: Waiting to deliver" this string can get printed many times.
What you are trying to achieve is looks like producer-consumer problem.
You required two semaphore to achive this.
main function:
while(1)
{
if (coin==0)
{
printf("no coin: please enter coin\n");
scanf("%d",&coin);
}
else
{
sem_post(&sem1);
sem_wait(&sem2)
}
}
in thread function
while(1)
{
printf("I'm %s\n",(char *)arg);
sem_wait(&sem1);
printf("Delivered...\n");
coin=0;
sem_post(&sem2)
}
Upvotes: 0
Reputation: 1335
Semaphores are used to control Critical-Section Access. In this case, critical section would be the output shell. The thread may or may not start promptly when the pthread_create() is called. Also, sem_wait() will decrease the value of sem1 with each call. Thus, when you include sleep(1) in the thrdFun1 function, there may be undefined behaviour :)
Upvotes: 3
Reputation: 6606
You need to remove sleep(1);
from function thrdFun1
. After this there will not be any need of sleep(1)
in main.
Upvotes: 1