在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可能由不同的线程调用。
答案 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;
}