Sem_wait()在第一个真实条件后没有阻塞

时间:2013-07-05 05:31:50

标签: c synchronization semaphore

我正在学习使用信号量,下面是我尝试实现的一个小场景。它在某种程度上表现得很奇怪。 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);
    }
}       

4 个答案:

答案 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)
    }