我开始怀疑信号量的概念;请好好阅读以理解我的问题。。。
根据手册,当信号量的值大于0
时,sem_post
将解锁线程。。。所以如果我有这个代码:
void* producer(void* arg)
{
while(1)
{
sem_wait(&sem_produce);
sem_wait(&mutex);
// Insert item into buffer
sem_post(&mutex);
sem_post(&sem_consume);
}
pthread_exit(NULL);
}
void* consumer(void* arg)
{
while(1)
{
sem_wait(&sem_consume);
sem_wait(&mutex);
// Remove item from buffer
sem_post(&mutex);
sem_post(&sem_produce);
}
pthread_exit(NULL);
}
其中sem_consume
用0
的值初始化,sem_produce
用N
初始化。
例如,如果N
消费者在生产者之前运行并尝试消费,会发生什么?那么sem_consume
应该有-N
的值,如果有N
插入,sem_consume
和sem_produce
都应该是0
,或者我错了吗?这意味着消费者将被卡住,因为(根据手册)当信号量的值变得大于零时,sem_post
将解锁线程。。。
因此,根据我从手册中了解到的情况,并考虑到上面的例子,如果sem_consume
永远不会达到-N
的值,那么这个程序才能正常工作。
我是对的?如果是,我该如何改进示例,使其不会陷入困境?如果答案是否定的,我错在哪里?
因此,根据我从手册中的理解,并考虑到以上内容例如,如果sem_consume永远不要达到-N的值。
这是正确的,信号量只是平坦的,不允许是负值周期。正如许多人在评论中指出的那样,信号量手册明确指出:
信号量是一个整数,其值永远不允许低于零
这个:
如果信号量当前的值为零,则调用将阻塞,直到可以执行递减(即信号量值上升到零以上)或者信号处理程序中断呼叫。
这个:
递减是一种(可能)阻塞函数。如果得到的信号量值为负,则调用线程或进程被阻塞,并且在其他线程或进程将其递增之前无法继续
本质上,信号量为正的全部意义在于,当一个进程试图将其递减为负时,该进程将停止,直到另一个进程将其递增到足够的程度,使其在允许原始进程递减时不会变为负。
致您的评论:
这很奇怪,在我的并行编程课程中,我想我从老师那里听说信号量的值可能是负数,这个负值表示阻塞线程的数量,如果这个值不能是负数,那么我毫无疑问。
本质上就是这样,但您无法查看此值。如果您试图获取当前不是正的信号量,那么尝试获取它的函数将被阻止,直到它再次变为正。
我认为sem_post和sem_wait的定义如下。
sem_wait()将信号量的值减1,如果值为负数,则等待。
sem_post()将信号量的值增加一,如果有一个或多个线程在等待,则唤醒一个线程。
因此,sem_post()并不会真正检查该值是否大于0。
此外,如果sem_post()真的检查了这一点,那么信号量永远不能用作锁。请参阅下面的代码片段。
sem_t m;
sem_init(&m, 0, 1)
sem_wait(&m)
... critical section...
sem_post(&m)
比方说,线程1首先得到调度,并将值减为0,然后进入关键部分。在它完成之前,其他三个线程会被一个接一个地调度,每个线程都会进一步减少信号量和块。现在,线程1再次得到调度,完成关键部分并调用sem_post()。我的观点是,如果它真的检查了一个正值,那么其他线程将永远不会被调度,事实并非如此。如果这能回答你的问题,请告诉我。
谢谢。