我想使用信号量使线程阻塞,直到信号量变为正数;但是当我的线程阻塞信号量时,它们会立即在被调用的第一个sem_post
上解锁,而不管之后该信号量的值是什么。
情况如下:
-1
。5
秒。5
秒过去,该帖子就会发布到信号量。0
,但无论如何主要进程都会解锁。以下是展示情况的代码:
/**
* testing whether sem_post on semaphore unblocks threads
* despite still being negative.
**/
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
sem_t sem;
void *proc(void *arg)
{
sleep(5);
puts("posting");
sem_post(&sem);
}
void setup()
{
pthread_t pt;
pthread_create(&pt, 0, proc, 0);
}
int main(int argc, char **argv)
{
sem_init(&sem, 0, -1);
setup();
sem_wait(&sem);
return 0;
}
我找到了一种粗略的方法来解决这个问题,方法是将sem_wait
包装在一个繁忙的循环中,检查信号量的值是否为0
,但这似乎是一种错误的解决方法。
是否有更优雅的方法来阻止信号量,直到它的值为正(不是0
,也不是负数)?
答案 0 :(得分:1)
您无法将信号量初始化为int sem_init(sem_t *sem, int pshared, unsigned int value);
,因为初始化它的API仅采用无符号值。
可能使用SEM_VALUE_MAX
导致大于sem_init()
的值传递给errno
,初始化实际上失败了。您应该检查返回代码,如果EINVAL
设置为sem_init()
。
如果符合以下情况,
EINVAL
功能将失败:
[ SEM_VALUE_MAX
] 值参数超过sem_wait
。...
<子> The Open Group 子>
如果您希望首次调用0
时线程阻塞信号量,请将信号量初始化为sem_getvalue
。
如果您的系统支持,如果计数为0
,您可以使用sem_getvalue()
查找信号量上的服务员数量。
如果 sem 被锁定,则
0
返回的值为零或负数,其绝对值表示等待信号量的进程数在通话过程中某些未指定的时间 <子> The Open Group 子>
允许实现选择他们想要的行为,因此这仅在您的系统支持时才有效。例如,Linux不支持它,因为如果信号量计数为0
,它会选择返回sem_wait(3)
。
如果一个或多个进程或线程被阻塞等待锁定 带
sval
的信号量,POSIX.1允许两种可能性0
中返回的值:返回sem_wait(3)
;或负数 其绝对值是进程数的计数 目前在extern pthread_mutex_t lock; extern pthread_cond_t queue; extern atomic_uint waiters; /* assume waiters is initially 0 */ pthread_mutex_lock(&lock); ++waiters; while (my_status() == WAITING) { pthread_cond_wait(&queue, &lock); } --waiters; pthread_mutex_unlock(&lock);
中阻止的主题。 Linux采用前者 行为。强>
<子> The Open Group 子>
实现您想要的最可靠的方法可能是使用互斥变量,条件变量和计数器。
{{1}}
答案 1 :(得分:0)
尝试使用零或正整数值初始化信号量。如果您使用零sem_init(&sem, 0, 0);
初始化,您将看到所需的行为。