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 more than one thread to enter if the count permits.
⚖️

Quick Comparison

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

FactorMutexSemaphore
PurposeEnsures exclusive access to a resourceControls access to multiple instances of a resource
AccessOnly one thread can hold the lock 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

A mutex is a simple locking tool that allows only one thread to enter a critical section at a time. It has a binary state: locked or unlocked. When a thread locks a mutex, other threads trying to lock it will wait until it is unlocked. The mutex is usually owned by the thread that locked it, which helps prevent errors like unlocking by a different thread.

On the other hand, a semaphore uses a counter to allow multiple threads to access a limited number of resources simultaneously. The counter decreases when a thread acquires the semaphore and increases when it releases it. If the counter reaches zero, threads trying to acquire the semaphore will block until another thread releases it. Semaphores do not have ownership, so any thread can release them.

In summary, use a mutex when you need exclusive access to a resource, and use a semaphore when you want to limit concurrent access to a resource pool.

💻

Mutex Code Example

This example shows how a mutex ensures exclusive access to a shared counter in C using POSIX threads.

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

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
int counter = 0;

void* increment(void* arg) {
    for (int i = 0; i < 100000; i++) {
        pthread_mutex_lock(&lock);
        counter++;
        pthread_mutex_unlock(&lock);
    }
    return NULL;
}

int main() {
    pthread_t t1, t2;
    pthread_create(&t1, NULL, increment, NULL);
    pthread_create(&t2, NULL, increment, NULL);
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    printf("Final counter value: %d\n", counter);
    return 0;
}
Output
Final counter value: 200000
↔️

Semaphore Equivalent

This example uses a semaphore to limit access to a resource pool of size 3 in C with POSIX threads.

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

sem_t sem;

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

int main() {
    pthread_t threads[5];
    sem_init(&sem, 0, 3); // Initialize semaphore with count 3

    for (long i = 0; i < 5; i++) {
        pthread_create(&threads[i], NULL, worker, (void*)i);
    }
    for (int i = 0; i < 5; i++) {
        pthread_join(threads[i], NULL);
    }
    sem_destroy(&sem);
    return 0;
}
Output
Thread 0 entered Thread 1 entered Thread 2 entered Thread 0 leaving Thread 3 entered Thread 1 leaving Thread 4 entered Thread 2 leaving Thread 3 leaving Thread 4 leaving
🎯

When to Use Which

Choose a mutex when you need to protect a shared resource so that only one thread can access it at a time, such as updating a shared variable or writing to a file.

Choose a semaphore when you want to allow a limited number of threads to access a resource simultaneously, like controlling access to a fixed number of database connections or slots.

In short, use mutex for exclusive locking and semaphore for managing concurrent access limits.

Key Takeaways

Mutex allows only one thread to access a resource at a time with ownership control.
Semaphore uses a counter to allow multiple threads limited concurrent access.
Use mutex for exclusive access to critical sections.
Use semaphore to limit the number of threads accessing a resource pool.
Mutex blocks threads until unlocked; semaphore blocks when count is zero.