我正在学习使用信号量,下面是我尝试实现的一个小场景。它在某种程度上表现得很奇怪。 sem_wait()第一次被解锁后,它不再被阻塞并继续循环,没有得到原因。这是使用信号量的正确方法吗?
编辑:我刚刚意识到,如果我在sem_post之后取消注释,它可以正常工作。 .Reason是它反复做sem_post()之前线程可以做硬币= 0我相信。但用信号量以这种方式使用睡眠是否正确。我相信这会被认为是一种不好的做法吗?#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);
}
}
答案 0 :(得分:2)
信号量用于控制关键部分访问。在这种情况下,关键部分将是输出shell。调用pthread_create()时,线程可能会或可能不会立即启动。此外,sem_wait()将在每次调用时减小sem1的值。因此,当您在thrdFun1函数中包含sleep(1)时,可能存在未定义的行为:)
答案 1 :(得分:1)
您需要从功能sleep(1);
中删除thrdFun1
。在此之后,主要内容中不需要sleep(1)
。
答案 2 :(得分:1)
您意识到这是正确的,在删除所有sem_post()
时,线程可以coin=0
重复执行sleep
。
要解决这个问题,你可以使用第二个信号量(你已经尝试过了),如下所示,
#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");
}
}
答案 3 :(得分:0)
有可能“Thread1:Waiting to deliver”这个字符串可以多次打印。
您想要实现的目标看起来像生产者 - 消费者问题。
你需要两个信号量来实现这个目标。
主要功能:
while(1)
{
if (coin==0)
{
printf("no coin: please enter coin\n");
scanf("%d",&coin);
}
else
{
sem_post(&sem1);
sem_wait(&sem2)
}
}
线程函数中的
while(1)
{
printf("I'm %s\n",(char *)arg);
sem_wait(&sem1);
printf("Delivered...\n");
coin=0;
sem_post(&sem2)
}