如何在C中初始化二进制信号量

时间:2011-09-19 23:59:20

标签: c linux semaphore init

man page中,即使您将信号量初始化为值1,也会显示:

sem_init(&mySem, 0, 1);

多次调用

时,它仍然可以增加到大于1的值
sem_post(&mySem);

但在这篇code example中,评论似乎有不同的看法:

sem_init(&mutex, 0, 1);      /* initialize mutex to 1 - binary semaphore */

是否可以在C中初始化严格的二进制信号量?

注意:在这种情况下执行此操作而不是使用互斥锁的原因是sem_post和sem_wait可能由不同的线程调用。

2 个答案:

答案 0 :(得分:9)

如果你想在Linux上使用严格的二进制信号量,我建议用互斥量和条件变量构建一个。

struct binary_semaphore {
    pthread_mutex_t mutex;
    pthread_cond_t cvar;
    int v;
};

void mysem_post(struct binary_semaphore *p)
{
    pthread_mutex_lock(&p->mutex);
    if (p->v == 1)
        /* error */
    p->v += 1;
    pthread_cond_signal(&p->cvar);
    pthread_mutex_unlock(&p->mutex);
}

void mysem_wait(struct binar_semaphore *p)
{
    pthread_mutex_lock(&p->mutex);
    while (!p->v)
        pthread_cond_wait(&p->cvar, &p->mutex);
    p->v -= 1;
    pthread_mutex_unlock(&p->mutex);
}

答案 1 :(得分:0)

这里是一个示例,为什么接受的答案不能完全用作二进制信号量。如果接受的答案有效,则线程_2第二次调用sem_wait时不应阻塞。但是它确实阻止了对sem_wait的第二次调用(第二次通过循环),因为它错过了thread_1的“ sem_post”

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

struct binary_semaphore {
    pthread_mutex_t mutex;
    pthread_cond_t cvar;
    int v;
};

void mysem_post(struct binary_semaphore *p)
{
    pthread_mutex_lock(&p->mutex);
    if (p->v == 1)
        /* error */
    p->v += 1;
    pthread_cond_signal(&p->cvar);
    pthread_mutex_unlock(&p->mutex);
}

void mysem_wait(struct binary_semaphore *p)
{
    pthread_mutex_lock(&p->mutex);
    while (!p->v)
        pthread_cond_wait(&p->cvar, &p->mutex);
    p->v -= 1;
    pthread_mutex_unlock(&p->mutex);
}

struct binary_semaphore b_sem = {
  .mutex = PTHREAD_MUTEX_INITIALIZER,
  .cvar  = PTHREAD_COND_INITIALIZER,
  .v     = 1
};



int thread_2_working = 0;

void* thread_1(void *arg)
{
  printf("thread_1 started\n");
    while(!thread_2_working)
    {
     // wait until thread 2 starts work
    }

    // post sem as soon as thread_2 starts working to simulate
    mysem_post(&b_sem);

    printf("thread 1 sem posted...\n");

  return NULL;
}

void* thread_2(void *arg)
{
  printf("thread 2 started\n");

  while(1)
  {
    mysem_wait( &b_sem );
    printf("thread 2 start\n");
    thread_2_working = 1;
    sleep(3); // fake time consuming work
    printf("thread 2 stop\n");
  }

  return NULL;
}

int main(void) {

  pthread_t thread_1_id, thread_2_id;
  pthread_create( &thread_1_id, NULL, thread_1, NULL );
  pthread_create( &thread_2_id, NULL, thread_2, NULL );

  pthread_join(thread_2_id, NULL);

  printf("Hello World\n");
  return 0;
}