0

我正在学习使用信号量,下面是我尝试实现的一个小场景。它在某种程度上表现得很奇怪。在 sem_wait() 第一次被解除阻塞后,它不再被阻塞并继续循环,不知道为什么。这是使用信号量的正确方法还是正确的场景?

编辑:我刚刚意识到,如果我在 sem_post 之后取消注释睡眠,它工作正常。.原因是在线程可以执行 coin=0 之前反复执行 sem_post() 我相信。但是以这种方式与信号量一起使用睡眠是否正确。我相信这会被认为是一种不好的做法?

#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);
    }
}       
4

4 回答 4

2

信号量用于控制关键部分的访问。在这种情况下,临界区将是输出外壳。当调用 pthread_create() 时,线程可能会也可能不会立即启动。此外, sem_wait() 将在每次调用时减少 sem1 的值。因此,当您在 thrdFun1 函数中包含 sleep(1) 时,可能会有未定义的行为:)

于 2013-07-05T05:44:48.490 回答
1

您意识到它是正确的,它在删除所有s时sem_post()线程可以做之前重复做。coin=0sleep

为了解决这个问题,您可以使用第二个信号量(您似乎已经尝试过),如下所示,

#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");
    }
}
于 2013-07-05T06:10:33.200 回答
1

您需要sleep(1);从功能中删除thrdFun1。在此之后将不再需要sleep(1)in main。

于 2013-07-05T05:41:01.993 回答
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)
    }
于 2013-07-05T06:09:03.683 回答