c-Sem_wait()在第一个true条件后未阻塞



我正在学习使用信号量,下面是我尝试实现的一个小场景。它的行为在某种程度上很奇怪。在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 delivern";
    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 coinn"); 
        scanf("%d",&coin);
        }
    else
        {
        sem_post(&sem1);
//      sleep(1);
        }
    }
    return 0;
}
void *thrdFun1(void *arg)
{
    while(1)
    {
        printf("I'm %sn",(char *)arg);
    sem_wait(&sem1);
    printf("Delivered...n");
    coin=0;
    sleep(1);
    }
}       

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

您需要从函数thrdFun1中删除sleep(1);。在此之后,基本上将不再需要sleep(1)

您意识到了这一点,当删除所有sleep s时,它在线程可以执行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 delivern";
    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 coinn");
                    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 %sn",(char *)arg);
            sem_wait(&sem1);    // Wait to spin the coin
            coin=0;
            sem_post(&sem2);    // inform as caught
            printf("Delivered...n");
    }
}

"Thread1:等待传递"这个字符串可能会被打印多次。

你们试图达到的目标看起来像是生产者和消费者的问题。

你需要两个信号量才能做到这一点。

主要功能:

while(1)
    {
    if (coin==0)
        {
        printf("no coin: please enter coinn"); 
        scanf("%d",&coin);
        }
    else
        {
        sem_post(&sem1);
        sem_wait(&sem2) 
        }
    }

线程内函数

while(1)
    {
        printf("I'm %sn",(char *)arg);
        sem_wait(&sem1);
        printf("Delivered...n");
        coin=0;
        sem_post(&sem2)
    }

最新更新