我试图理解信号量的语义。
这是一些代码:
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
sem_t sem;
void *helper(void *arg) {
sem_wait(&sem);
printf("helper woke up\n");
return NULL;
}
int main() {
sem_init(&sem, 0, 0);
pthread_t tid;
pthread_create(&tid, NULL, helper, NULL);
sleep(1);
sem_post(&sem);
sem_wait(&sem);
printf("main woke up\n");
exit(0);
}
这里 main 创建一个辅助线程,休眠一秒钟以(几乎)确定辅助线程已运行并等待信号量,然后尝试快速连续地发布并等待信号量。根据 POSIX ( https://pubs.opengroup.org/onlinepubs/009695399/functions/sem_post.html ):
如果此操作产生的信号量的值为零,则应允许阻塞等待信号量的线程之一从其对 的调用成功返回
sem_wait()
。
所以,我希望打印出“助手醒来”。但是,如果您实际在 Linux 上运行此代码,通常会观察到“main 唤醒”,这意味着默认情况下 Linux 上的信号量是允许不公平的。
我的问题是:为什么允许这种行为?是的,您可以说“它更容易实现”,但这并不能解释为什么信号量是用这些特定的语义设计的。
在其他地方(https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Semaphore.html)它表示这种行为在某些情况下更可取。在什么情况下非公平信号量更好?如果有关于这个主题的详细资料,我将不胜感激。
编辑:请不要让睡眠(1)成为帖子的焦点。假设辅助线程以您喜欢的任何方式(yield、barrier、无计时器滴答等)等待信号量(就像它几乎总是那样)。我对这里的信号量语义感兴趣。