首页 > 解决方案 > 在多线程环境中在 sem_wait 之前调用 sem_post

问题描述

对于基于二进制信号量的实现,该sem_post()函数的行为尚不清楚。

sem_wait()打电话后打电话会发生什么sem_post()。它会起作用吗。

代码示例:

线程 1:

do_something_critical()
sem_post();

线程 2:

sem_wait()
Proceed()

在这里,如果sem_post()在调用 to 之前调用了一些方法sem_wait(),它会起作用吗?还是有必要sem_wait()在之前调用sem_post()

标签: multithreadingmutexsemaphorebinary-semaphore

解决方案


sem_post()只是增加信号量并唤醒任何等待线程(如果有)。否则它什么也不做。

sem_wait()只是减少信号量。仅当信号量的当前值为 0 时,调用方才会被阻塞。

这是一个示例程序,其中主线程将信号量初始化为 0,并调用sem_trywait()来验证信号量是否忙(即值为 0)。然后,它调用sem_post()在创建线程之前释放信号量(即值为 1)。线程调用sem_wait()(这将信号量减为 0)并返回。主线程等待线程结束并通过调用sem_trywait()验证信号量是否为 0 :

#include <pthread.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <stdio.h>
#include <errno.h>

static sem_t *sem;

void *thd_entry(void *p)
{
int rc;

  printf("Thread is starting...\n");

  // This decrements the semaphore
  rc = sem_wait(sem);
  if (0 != rc) {
    perror("sem_wait()");
    return NULL;
  }

  printf("Thread is exiting...\n");

  return NULL;

}

int main(int ac, char *av[])
{
int        rc;
pthread_t  thd;

  // Create a semaphore with an initial value set to 0
  sem = sem_open("/example", O_CREAT|O_RDWR, 0777, 0);
  if (sem == SEM_FAILED) {
    perror("sem_open()");
    return 1;
  }

  // After creation the value of the semaphore is 0
  rc = sem_trywait(sem);
  if (-1 == rc) {
    if (errno == EAGAIN) {
      printf("Semaphore is busy (i.e. value is 0)\n");
    } else {
      perror("sem_trywait()");
      return 1;
    }
  }

  // Increment the semaphore
  rc = sem_post(sem);
  if (0 != rc) {
    perror("sem_post()");
    return 1;
  }

  // Create a thread
  rc = pthread_create(&thd, NULL, thd_entry, 0);
  if (0 != rc) {
    errno = rc;
    perror("pthread_create()");
    return 1;
  }

  rc = pthread_join(thd, NULL);
  if (0 != rc) {
    errno = rc;
    perror("pthread_join()");
    return 1;
  }

  // The semaphore is 0 as the thread decremented it
  rc = sem_trywait(sem);
  if (-1 == rc) {
    if (errno == EAGAIN) {
      printf("Semaphore is busy (i.e. value is 0)\n");
    } else {
      perror("sem_trywait()");
      return 1;
    }
  }

  return 0;
}

这是一个尝试:

$ ls -l /dev/shm
total 0
$ gcc sema.c -o sema -lpthread
$ ./sema 
Semaphore is busy (i.e. value is 0)
Thread is starting...
Thread is exiting...
Semaphore is busy (i.e. value is 0)
$ ls -l /dev/shm
total 4
-rwxrwxr-x 1 xxxxx xxxxx 32 janv.   5 16:24 sem.example
$ rm /dev/shm/sem.example

推荐阅读