如何阻止信号量直到它的值为正

时间:2016-04-19 22:20:03

标签: c multithreading pthreads semaphore

我想使用信号量使线程阻塞,直到信号量变为正数;但是当我的线程阻塞信号量时,它们会立即在被调用的第一个sem_post上解锁,而不管之后该信号量的值是什么。

情况如下:

  1. 信号量设置为-1
  2. 在发布到信号量之前,线程开始等待5秒。
  3. 一旦5秒过去,该帖子就会发布到信号量。
  4. 信号量的值为0,但无论如何主要进程都会解锁。
  5. 以下是展示情况的代码:

    /**
     * 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,也不是负数)?

2 个答案:

答案 0 :(得分:1)

您无法将信号量初始化为int sem_init(sem_t *sem, int pshared, unsigned int value);,因为初始化它的API仅采用无符号值。

  

-1
  <子> enter image description here

可能使用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);初始化,您将看到所需的行为。