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

标签 c multithreading posix semaphore

这道题要求使用两个信号量,一个作为互斥信号量,一个作为计数信号量,并且用这对信号量来模拟学生和助教之间的交互。
我已经能够足够轻松地利用二进制信号量,但是我似乎找不到很多显示计数信号量使用的示例,所以我很确定我错了,这导致我的代码无法正确执行。< br/> 我的代码如下

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

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

最佳答案

我不确定您的类(class)/老师是否想在这里进行特殊区分,但从根本上来说,二进制信号量主要相当于初始化为 1,1 的共分信号量,因此当您计数时当它下降(“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真正的二进制信号量和计数信号量之间的真正区别在于,二进制信号量不提供计数功能。它要么已获取(并且获取将阻止),要么未获取(并且获取将成功并阻止其他获取)。各种实现可能会考虑将已经发布的二进制信号量释放为无操作或错误(例如,运行时 panic )。 POSIX 根本不提供二进制信号量:sem_init 初始化一个计数信号量,您有责任将其设置为 1,并且在信号量已经释放时不要通过释放来过度递增它。另请参阅下面的评论。

关于c - 使用 posix C 同时多次轮询信号量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20454097/

相关文章:

c - 虚拟内存如何保持其效率?

c - 两个文件描述符都关闭后,Linux 会自动释放未命名的管道吗?

java - 线程中出现异常 "main"java.lang.OutOfMemoryError : unable to create new native thread

Java "Fire and Forget"线程

c - 使用共享内存时如何处理被杀(kill -9)?

c - 减法运算不起作用

c - 如何使用 : "\\" or "\"? 分割字符串

cocoa - 如果我不在创建对象的线程上显式访问它们,那么操作在线程外部创建的对象是否安全?

posix - 我应该期望 POSIX 包含 getopt.h 吗?

C 父级和 2 个子级之间的管道