I’m trying to understand the semantics of semaphores.
Here is some code:
#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 upn");
}
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 upn");
exit(0);
}
Here main creates a helper thread, sleeps for a second to be (almost) sure that the helper has run and waited on the semaphore, and then tries to post and wait on the semaphore in quick succession. According to POSIX (https://pubs.opengroup.org/onlinepubs/009695399/functions/sem_post.html), when a thread sem_posts and there is another thread waiting on that semaphore, one of the waiters shall be woken up and allowed to return from sem_wait. So, I would expect “helper woke up” to be printed. However, if you actually run this code on Linux, “main woke up” is typically observed, meaning that by default semaphores on Linux are allowed to be not fair. My question is: why is this behavior allowed? Yes, you can say “it’s easier to implement” but that does not explain why semaphores have been designed with these particular semantics.
Elsewhere, (https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Semaphore.html) it says that this behavior is preferable in some situations. In what situation would a non-fair semaphore be preferable? I’d appreciate any detailed source on this topic.
Josh Levi is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.