WikiGalaxy

Personalize

Mutex and Semaphores

Introduction

Mutexes and semaphores are synchronization primitives used in operating systems to manage concurrent processes and threads, ensuring that resources are accessed in a controlled manner.

Mutex

  • Mutual Exclusion: A mutex ensures that only one thread accesses a resource at a time.
  • Locking Mechanism: Threads must acquire the mutex lock before accessing the resource and release it afterward.
  • Binary State: Mutexes have two states - locked and unlocked.
  • Ownership: Only the thread that locks the mutex can unlock it.

Semaphore

  • Counting Mechanism: Semaphores can count, allowing multiple threads to access a resource up to a defined limit.
  • Signal and Wait: Threads can signal (increment) or wait (decrement) the semaphore.
  • No Ownership: Any thread can signal or wait on a semaphore.
  • Use Cases: Useful for managing access to a finite number of resources.

Mutex Lock Implementation

Description

Mutex locks are used to protect shared data by ensuring that only one thread can access the data at any given time. This prevents race conditions and data corruption.


import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class SharedResource {
    private final Lock lock = new ReentrantLock();
    private int counter = 0;

    public void increment() {
        lock.lock();
        try {
            counter++;
        } finally {
            lock.unlock();
        }
    }

    public int getCounter() {
        return counter;
    }
}
        

Explanation

In this example, a ReentrantLock is used to protect the increment operation on a shared counter. The lock ensures that only one thread can execute the critical section at a time.

Semaphore for Resource Management

Description

Semaphores are often used to control access to a pool of resources, such as database connections, where multiple threads can access up to a specified number of resources simultaneously.


import java.util.concurrent.Semaphore;

class ResourcePool {
    private final Semaphore semaphore;

    public ResourcePool(int maxResources) {
        semaphore = new Semaphore(maxResources);
    }

    public void acquireResource() throws InterruptedException {
        semaphore.acquire();
        // Access the resource
    }

    public void releaseResource() {
        semaphore.release();
    }
}
        

Explanation

This example demonstrates a semaphore controlling access to a pool of resources. The semaphore's permits represent the available resources, and threads must acquire a permit to access a resource.

Mutex in Multi-threading

Description

In multi-threading environments, mutexes prevent race conditions by ensuring that only one thread can modify shared data at a time.


class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}

class CounterThread extends Thread {
    private final Counter counter;

    public CounterThread(Counter counter) {
        this.counter = counter;
    }

    @Override
    public void run() {
        counter.increment();
    }
}
        

Explanation

The synchronized keyword in Java acts as a mutex, ensuring that only one thread can execute the increment method at a time, thus preventing race conditions.

Semaphore for Thread Synchronization

Description

Semaphores can also be used to synchronize threads, ensuring that certain operations are performed in the correct order.


import java.util.concurrent.Semaphore;

class Task {
    private final Semaphore semaphore = new Semaphore(1);

    public void performTask() throws InterruptedException {
        semaphore.acquire();
        try {
            // Perform task
        } finally {
            semaphore.release();
        }
    }
}
        

Explanation

In this example, a semaphore is used to ensure that only one thread can perform a specific task at a time, synchronizing the threads.

Mutex vs Semaphore Differences

Description

Understanding the differences between mutexes and semaphores is crucial for selecting the appropriate synchronization primitive for a given problem.


// Mutex: Binary lock, ownership required
// Semaphore: Counting mechanism, no ownership

class MutexExample {
    private final Object lock = new Object();

    public void criticalSection() {
        synchronized (lock) {
            // Critical section
        }
    }
}

class SemaphoreExample {
    private final Semaphore semaphore = new Semaphore(5);

    public void accessResource() throws InterruptedException {
        semaphore.acquire();
        try {
            // Access resource
        } finally {
            semaphore.release();
        }
    }
}
        

Explanation

This example highlights the key differences: mutexes are binary locks with ownership, while semaphores are counting mechanisms without ownership restrictions.

Mutex for Deadlock Prevention

Description

Proper use of mutexes can help prevent deadlocks, a situation where two or more threads are blocked forever, each waiting for the other to release a resource.


class DeadlockPrevention {
    private final Object lock1 = new Object();
    private final Object lock2 = new Object();

    public void method1() {
        synchronized (lock1) {
            synchronized (lock2) {
                // Perform action
            }
        }
    }

    public void method2() {
        synchronized (lock2) {
            synchronized (lock1) {
                // Perform action
            }
        }
    }
}
        

Explanation

This example illustrates how ensuring a consistent lock order can prevent deadlocks, allowing threads to acquire locks in the same order.

Semaphore for Traffic Light Control

Description

Semaphores can be used in real-world applications like traffic light control systems, where they manage the flow of vehicles at intersections.


import java.util.concurrent.Semaphore;

class TrafficLight {
    private final Semaphore greenLight = new Semaphore(1);

    public void passThrough() throws InterruptedException {
        greenLight.acquire();
        try {
            // Vehicle passes through
        } finally {
            greenLight.release();
        }
    }
}
        

Explanation

In this scenario, the semaphore controls the traffic light, allowing one vehicle to pass through the intersection at a time.

Mutex and Semaphore Combined Use

Description

Sometimes, both mutexes and semaphores are used together to achieve complex synchronization requirements.


import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class HybridSynchronization {
    private final Semaphore semaphore = new Semaphore(3);
    private final Lock lock = new ReentrantLock();

    public void performOperation() throws InterruptedException {
        semaphore.acquire();
        lock.lock();
        try {
            // Perform operation
        } finally {
            lock.unlock();
            semaphore.release();
        }
    }
}
        

Explanation

This example demonstrates using a semaphore to limit concurrent access and a mutex to protect critical sections, combining their strengths for robust synchronization.

logo of wikigalaxy

Newsletter

Subscribe to our newsletter for weekly updates and promotions.

Privacy Policy

 • 

Terms of Service

Copyright © WikiGalaxy 2025