https://medium.com/@akshatarhabib/understanding-semaphores-in-c-04835e97024f


https://man7.org/linux/man-pages/man7/sem_overview.7.html



Normal posix threads code (no semaphores):

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void* thread_action(void* arg) {
    int thread_id = *(int*)arg;
    
    printf("Thread %d started\n", thread_id);
    sleep(1);
    printf("Thread %d finished\n", thread_id);

    return NULL;
}

int main() {
    pthread_t threads[10];
    int thread_ids[10];

    // create threads
    for (int i = 0; i < 10; i++) {
        thread_ids[i] = i + 1;
        pthread_create(&threads[i], NULL, thread_action, &thread_ids[i]);
    }

    // wait for all threads to finish executing
    for (int i = 0; i < 10; i++) {
        pthread_join(threads[i], NULL);
    }

    printf("All threads finished.\n");
    return 0;
}





Now what if you only want say a maximum of 3 threads to execute at a time?


You can use semaphores!


#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>


sem_t my_semaphore;

void* thread_action(void* arg) {
    int thread_id = *(int*)arg;

    //printf("Thread %d waiting to start...\n", thread_id);

    // decrement semaphore (block if value is 0)
    sem_wait(&my_semaphore); 



    //printf("Thread %d started\n", thread_id);
    sleep(1);
    printf("Thread %d finished\n", thread_id);



    // increment semaphore when finished
    sem_post(&my_semaphore); 

    return NULL;
}

int main() {
    pthread_t threads[10];
    int thread_ids[10];


    /*
     * Initialize semaphore:
     * Argument 1: Pointer to the semaphore
     * Argument 2: 0 means shared between threads; non-zero means between processes
     * Argument 3: Initial value (3 threads allowed at a time)
     */
    sem_init(&my_semaphore, 0, 3);

    for (int i = 0; i < 10; i++) {
        thread_ids[i] = i + 1;
        pthread_create(&threads[i], NULL, thread_action, &thread_ids[i]);
    }

    // Wait for all threads to finish execution
    for (int i = 0; i < 10; i++) {
        pthread_join(threads[i], NULL);
    }


    sem_destroy(&my_semaphore); // cleanup

    printf("All threads finished.\n");
    return 0;
}