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