【问题标题】:Sem_wait() not blocking after first true conditionSem_wait() 在第一个真条件后不阻塞
【发布时间】:2013-07-05 05:31:50
【问题描述】:

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

编辑:我刚刚意识到,如果我在 sem_post 之后取消注释 sleep,它可以正常工作。 .原因是在线程可以执行 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);
    }
}       

【问题讨论】:

  • coin 被初始化为0 并且除了0 之外永远不会设置为任何值。 thrdFun1() 应该永远等待。
  • 它只设置为 0,但 sem_post() 只会在用户输入除 0 以外的任何内容时发生。只是一种假设情况。所以我希望它是正确的方式

标签: c synchronization semaphore


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      你没看错,在删除所有sleeps时,线程可以在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);    // 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");
          }
      }
      

      【讨论】:

      • 是的,使用两个信号量我可以轻松做到这一点。但是,如果可能的话,只是尝试学习,只使用一个:D
      • @DiwakarSharma 是的,只有一个 sem,通过在 main 中的 post 之后设置 coin=0 :)
      【解决方案4】:

      “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)
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-02-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-02
        • 2022-01-20
        • 1970-01-01
        相关资源
        最近更新 更多