POSIX 标准和信号量语义

问题描述 投票:0回答:1

我正在尝试理解信号量的语义。

这是一些代码:

#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");
}

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)它表示这种行为在某些情况下更可取。在什么情况下非公平信号量更好?我将不胜感激有关此主题的任何详细资料。

c multithreading posix semaphore
1个回答
0
投票

这样做的一个更好的方法是它减少了上下文切换。允许调用

sem_post()
的线程继续运行,而不必恢复在
sem_wait()
中阻塞的线程。

当调度程序决定解除哪个线程的阻塞时,主线程已调用

sem_wait()
。然后它选择要解除封锁的服务员。然后,它可以根据调度优先级(如引用段落的其余部分所述)或任意选择。并且它可能会选择主线程以避免上下文切换。

© www.soinside.com 2019 - 2024. All rights reserved.