Concurrency Essentials

Mutex vs Semaphore

Master the art of multithreading. Understand the crucial difference between Locking (Ownership) and Signaling (Counting).

key
lock

Mutex

Short for Mutual Exclusion. Ideally used when you want to protect a shared resource (like a variable or file) so that only ONE thread can access it at a time.

lightbulb Key Concept: Ownership

A Mutex has an OWNER. If Thread A locks it, ONLY Thread A can unlock it.

wc

Real Life Example: The Toilet Key

A coffee shop has one restroom with one key. If you take the key, you "own" the restroom. No one else can enter until YOU return the key.

traffic
traffic

Semaphore

A signaling mechanism that maintains a counter. It controls access to a pool of resources or signals events between threads.

lightbulb Key Concept: Signaling

A Semaphore has NO OWNERSHIP. Thread A can wait (decrement), and Thread B can signal (increment). It's just a counter.

local_parking

Real Life Example: Parking Lot

A parking lot has 10 spots. A display shows "10 Free". Each car entering decrements the count. Each car leaving increments it. The car leaving doesn't need to be the same one that entered first.

Interactive Laboratory

Visualize the flow of threads in real-time

lock_open
Unlocked
Wait Queue
> System initialized...
> Switched to MUTEX mode.
info Click "New Thread" to simulate a request. Click "Release" to simulate a thread finishing.

Technical Implementation (C++)

mutex_example.cpp
#include <mutex>
#include <thread>

std::mutex mtx; // Global mutex
int shared_counter = 0;

void increment() {
    // RAII: Locks on creation, unlocks on destruction
    std::lock_guard<std::mutex> lock(mtx);
    
    // Critical Section
    shared_counter++;
    
    // Mutex automatically released here
}

int main() {
    std::thread t1(increment);
    std::thread t2(increment);
    
    t1.join();
    t2.join();
}

Note: Used to protect shared_counter from race conditions. Only one thread updates it at a time.

semaphore_example.cpp (C++20)
#include <semaphore>
#include <thread>

// Allow 3 concurrent threads
std::counting_semaphore<3> sem(3); 

void access_database() {
    sem.acquire(); // Decrement count, wait if 0
    
    // Access connection pool...
    // Up to 3 threads can be here simultaneously
    
    sem.release(); // Increment count, signal waiter
}

int main() {
    std::thread threads[10];
    for(int i=0; i<10; ++i) 
        threads[i] = std::thread(access_database);
        
    for(auto& t : threads) t.join();
}

Note: Used to throttle access. It doesn't lock data; it limits how many things happen at once.

school

How to Answer in an Interview?

"What is the difference between a Mutex and a Semaphore?"

1

The "One-Liner"

"The fundamental difference is Ownership. A Mutex is owned by the thread that locks it, whereas a Semaphore has no ownership concept."

2

The Conceptual Distinction

"A Mutex is a Locking Mechanism used for mutual exclusion of critical sections. A Semaphore is a Signaling Mechanism used to control access to a pool of resources or to coordinate between threads."

3

The "Gotcha" Detail

"Even a Binary Semaphore (value 0 or 1) is not exactly a Mutex. In a Mutex, only the owner can unlock. In a Semaphore, Thread A can wait on it, and Thread B can signal it. Doing this with a Mutex would be undefined behavior."