【问题标题】:Calling sem_post before sem_wait in multithreaded environment在多线程环境中在 sem_wait 之前调用 sem_post
【发布时间】:2021-04-10 23:58:57
【问题描述】:

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

在调用sem_post() 之后调用sem_wait() 会发生什么。 它会起作用吗?

代码示例:

线程 1:

do_something_critical()
sem_post();

线程 2:

sem_wait()
Proceed()

如果在调用sem_wait()之前调用sem_post(), 它会起作用吗?还是必须在sem_post()之前调用sem_wait()

【问题讨论】:

    标签: multithreading mutex semaphore binary-semaphore


    【解决方案1】:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-05
      • 2010-12-20
      • 1970-01-01
      • 1970-01-01
      • 2010-11-02
      相关资源
      最近更新 更多