当前位置: 首页 > 知识库问答 >
问题:

使用posix C同时多次轮询信号量

孙琨
2023-03-14

这个问题要求使用两个信号量,一个作为互斥量,一个作为计数信号量,并使用这两个信号量来模拟学生和教师助手之间的交互。
我已经能够很容易地使用二进制信号量,但是我似乎找不到很多例子来说明计数信号量的使用,所以我很确定我错了,这导致我的代码不能正确执行。
我的代码如下

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <semaphore.h>
#include <time.h>
#include <sys/types.h>

void *taThread();
void *student();

sem_t taMutex;
sem_t semaphore;

int main()
{
  pthread_t tid1;

  srand(time(NULL));

  sem_init(&taMutex,0,1);
  sem_init(&semaphore,1,3);

  pthread_create(&tid1, NULL, &taThread, NULL);
  pthread_join(tid1, NULL);
  return 0;
}


void *taThread()
{
  pthread_t tid2[10];
  int it = 0;

  printf("Teacher's Assistant taking a nap.\n");

  for (it =  0; it < 10; it ++)
  {
    pthread_create(&tid2[it], NULL, &student, NULL);
  }

  for (it = 0; it < 10; it ++)
  {
    pthread_join(tid2[it], NULL);
  }
}


void *student()
{
  int xTime;  
  xTime = rand() % 10 + 1;

  if (sem_wait(&taMutex) == 0)
  {
    printf("Student has awakened TA and is getting help. This will take %d       minutes.\n", xTime);
    sleep(xTime);
    sem_post(&taMutex);
  }
  else if (sem_wait(&semaphore) > 2 )
  {
    printf("Student will return at another time.\n");
  }
  else
  {
    sem_wait(&semaphore);

    printf("Student is working on their assignment until TA becomes available.\n");
    sem_wait(&taMutex);
    sem_post(&semaphore);
    printf("Student is entering the TA's office. This will take %d minutes", xTime);
    sleep(xTime);
    sem_post(&taMutex);
  }
}

我的主要问题是:如何让线程同时轮询计数信号量?
我正试图获得备份,一些学生被迫离开(或退出线程),而其他人则在信号量中等待。任何帮助都是感激的,任何澄清都将被提供。

共有1个答案

百里疏珂
2023-03-14

我不确定您的班级/老师是否想在这里做特殊的区分,但从根本上说,二进制信号量主要相当于初始化为1,1的copunting信号量,因此当您将其向下(“p”)计数到零时,它就变成了“忙”(像互斥锁一样锁定),而当您释放它(“v”)时,它的最大值为1,现在它变成了“非忙”(解锁)。计数信号量通常以较高的初始值开始,通常用于计数某些资源(比如一个房间里有3把可用的椅子),这样当您向下计数时,可能还剩下一些资源。当你使用完被计数的资源(例如,当“学生”离开“助教的办公室”时),你将它重新计数(“V”)。

使用POSIX信号量,调用:

sem_init(&semaphore,1,3);

表示这是进程共享信号量(第二个参数非零),而不是线程共享信号量;您似乎不需要这样做,而且我不确定某些系统是否会给您一个错误--失败的sem_init调用,也就是说--如果&semaphore不在进程共享区域中。您应该能够只使用0,3。否则,这很好:它实际上是在说“办公室”里有三把“空椅子”。

除此之外,您还需要使用sem_trywait(正如@pilcrow建议的那样)、sem_timedwait或中断sem_wait呼叫的信号(例如sigalrm),以便让一些试图在“办公室”中获得一个“座位”的学生发现他在某个时间段内无法获得一个“座位”。只要调用sem_wait就意味着“等到有一把空椅子,即使这需要很长时间”。只有两件事可以阻止这种潜在的无限等待:要么是椅子变得可用,要么是信号中断了通话。

(各种sem_*函数的返回值告诉您是否“得到”了您所等待的“椅子”。sem_wait等待“永远”,sem_trywait等待“根本不”,sem_timedwait等待,直到您“得到椅子”或时钟用完为止,以先发生者为准。)

1真正的二进制信号量和计数信号量之间的真正区别在于二进制信号量不提供计数能力。它要么是获取的(获取将阻止),要么是非获取的(获取将成功并阻止其他获取)。各种实现可能认为释放已经释放的二进制信号量是无操作或错误(例如,运行时恐慌)。POSIX根本不提供二进制信号量:sem_init初始化一个计数信号量,您的责任是将其设置为1,而不是在已经释放信号量时释放信号量。另见下面的评论。

 类似资料:
  • 问题内容: 我正在研究ajax长期轮询,但感到困惑。传统的ajax调用和长时间轮询有什么不同 此示例仅以递归方式调用服务器。与setInterval中的传统调用不同。 问题答案: 顾名思义,“ 长时间轮询” 意味着长时间轮询某些内容。 这是实际过程的开始,您对服务器上的某个脚本进行ajax调用,在本例中为,您需要使服务器脚本(例如)足够智能,以便仅在所需数据可用时才响应请求,该脚本应等待指定的时间

  • 本文向大家介绍详解Linux多线程使用信号量同步,包括了详解Linux多线程使用信号量同步的使用技巧和注意事项,需要的朋友参考一下 信号量、同步这些名词在进程间通信时就已经说过,在这里它们的意思是相同的,只不过是同步的对象不同而已。但是下面介绍的信号量的接口是用于线程的信号量,注意不要跟用于进程间通信的信号量混淆。 一、什么是信号量 线程的信号量与进程间通信中使用的信号量的概念是一样,它是一种特殊

  • 有没有办法找出上次spring集成成功检查消息的时间?具体来说,它最后一次运行时,无论是否找到可以转化为消息的内容,都没有出现错误? 我有一个邮件入站通道适配器(带有轮询器)连接到路由器,路由器将消息吐出到各个通道。

  • 问题内容: 我有一个包含多个CTE的相当复杂的查询,但是其他人都从中提取了1个主要CTE,这是否会导致该主要CTE多次执行? 问题答案: 您可以这样使用CROSS JOIN: 这将防止的多次执行(有关实际执行计划,请参见属性)。 示例:如果执行此查询 使用数据库,那么实际的执行计划将是

  • 我正在对PeopleSoft数据库进行查询,不确定是否可以根据初始查询在一次调用中从同一个表中获取信息。例如,我正在访问的表返回EmployeeID、FullName、FirstName、LastName、Position\u NBR和ReportsTo。但是ReportsTo是以经理的Position\u NBR(在同一个表中找到)的形式提供的,我想以name格式提供。我想这样做,但不确定是否可

  • 主要内容:文章目录,业务场景,1.定时任务轮询db,2.DelayQueue,3.redis的zset,4.RabbitMQ的TTL+DLX,5.对比业务场景 我们买火车票或者叫外卖的时候,下完单之后会跳转到支付页面,页面里通常会有一个计时器,要求在指定时间内完成支付,否则订单就会被自动取消。这就是延时任务的一个典型业务场景。分析这个场景,其实最关键的就是如何在订单超时的时候立即触发取消订单的动作。 1.定时任务轮询db 用户下单后db中会生成一条订单记录,记录了订单号、用户ID、创建时间、订单