0
0
Operating-systemsComparisonBeginner · 4 min read

Semaphore vs Mutex: Key Differences and When to Use Each

A mutex is a locking mechanism that allows only one thread to access a resource at a time, ensuring exclusive access. A semaphore is a signaling mechanism that controls access to a resource by multiple threads using a counter, allowing a limited number of threads to enter concurrently.
⚖️

Quick Comparison

Here is a quick side-by-side comparison of semaphore and mutex based on key factors.

FactorMutexSemaphore
PurposeEnsures exclusive access to a resourceControls access to a resource by multiple threads
AccessOnly one thread can hold the mutex at a timeMultiple threads can acquire if count > 0
CounterBinary (locked/unlocked)Integer count (can be >1)
OwnershipOwned by the thread that locks itNo ownership required
Use caseProtect critical sectionsLimit number of concurrent accesses
Blocking behaviorBlocks if already lockedBlocks if count is zero
⚖️

Key Differences

Mutex is a locking tool designed to provide exclusive access to a shared resource. Only one thread can lock the mutex at a time, and other threads must wait until it is unlocked. It has ownership, meaning the thread that locks it must unlock it, which helps prevent accidental release by other threads.

On the other hand, a semaphore uses a counter to allow multiple threads to access a resource concurrently up to a set limit. It does not have ownership, so any thread can signal (release) the semaphore. This makes semaphores useful for managing pools of resources like connections or slots.

In summary, use a mutex when you need strict exclusive access and ownership control, and use a semaphore when you want to limit concurrent access but allow multiple users simultaneously.

⚖️

Code Comparison

This example shows how a mutex protects a critical section so only one thread prints at a time.

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

pthread_mutex_t lock;

void* worker(void* arg) {
    pthread_mutex_lock(&lock);
    printf("Thread %ld entered critical section\n", (long)arg);
    sleep(1); // simulate work
    printf("Thread %ld leaving critical section\n", (long)arg);
    pthread_mutex_unlock(&lock);
    return NULL;
}

int main() {
    pthread_t threads[3];
    pthread_mutex_init(&lock, NULL);

    for (long i = 1; i <= 3; i++) {
        pthread_create(&threads[i-1], NULL, worker, (void*)i);
    }

    for (int i = 0; i < 3; i++) {
        pthread_join(threads[i], NULL);
    }

    pthread_mutex_destroy(&lock);
    return 0;
}
Output
Thread 1 entered critical section Thread 1 leaving critical section Thread 2 entered critical section Thread 2 leaving critical section Thread 3 entered critical section Thread 3 leaving critical section
↔️

Semaphore Equivalent

This example uses a semaphore to allow up to two threads to enter the critical section concurrently.

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

sem_t sem;

void* worker(void* arg) {
    sem_wait(&sem);
    printf("Thread %ld entered critical section\n", (long)arg);
    sleep(1); // simulate work
    printf("Thread %ld leaving critical section\n", (long)arg);
    sem_post(&sem);
    return NULL;
}

int main() {
    pthread_t threads[4];
    sem_init(&sem, 0, 2); // allow 2 concurrent threads

    for (long i = 1; i <= 4; i++) {
        pthread_create(&threads[i-1], NULL, worker, (void*)i);
    }

    for (int i = 0; i < 4; i++) {
        pthread_join(threads[i], NULL);
    }

    sem_destroy(&sem);
    return 0;
}
Output
Thread 1 entered critical section Thread 2 entered critical section Thread 1 leaving critical section Thread 3 entered critical section Thread 2 leaving critical section Thread 4 entered critical section Thread 3 leaving critical section Thread 4 leaving critical section
🎯

When to Use Which

Choose a mutex when you need to protect a resource so that only one thread can use it at a time, such as updating shared data or critical sections. Its ownership feature helps avoid accidental unlocking by other threads.

Choose a semaphore when you want to limit the number of threads accessing a resource simultaneously, like controlling access to a fixed-size pool of connections or slots. Semaphores are better for managing multiple identical resources.

Key Takeaways

Use a mutex for exclusive access and ownership control of a resource.
Use a semaphore to allow limited concurrent access with a counting mechanism.
Mutexes block other threads until unlocked by the owner thread.
Semaphores use a counter and do not require ownership for release.
Choose based on whether you need single-thread access (mutex) or limited multi-thread access (semaphore).