SoFunction
Updated on 2025-03-08

Methods to implement semaphores using synchronized keyword

Preface

In Java, Semaphore is a commonly used synchronization tool that can be used to control the number of accesses to shared resources. Semaphores are mainly used for two purposes: one is for the mutually exclusive use of multiple shared resources, and the other is for the control of the number of concurrent threads. Although JavaPackage providedSemaphoreclass, but understanding how to manually implement a semaphore can help to have a deeper understanding of the principles of concurrent programming.

Below, we will useSynchronizedKeywords to implement a simple semaphore. Our goal is to implement a counting semaphore, where the count of the semaphore indicates the number of threads that can access a certain resource simultaneously.

Implementing the basic framework

First, we define aSemaphoreclass, it needs to maintain a counter to track the number of available licenses. The initial value of the counter is provided by the constructor when the semaphore is created.

public class SimpleSemaphore {
    private int signals = 0;
    private int bound = 0;

    public SimpleSemaphore(int upperBound) {
         = upperBound;
    }
}

Implement acquire method

acquireMethod is used to obtain a license. If there is currently no license available (i.e.signalsEqual to the upper boundbound), then the method will block until a license is available.

public synchronized void acquire() throws InterruptedException {
    while (signals == bound) {
        wait();
    }
    signals++;
    notify();
}

Used heresynchronizedKeywords to ensure that the method is thread-safe. ifsignalsachievebound, callwait()Make the current thread wait untilsignalsReduce and continue to execute. Each callacquireWhen the method,signalsThey will increase and passnotify()Wake up the thread that may be waiting.

Implement the release method

releaseMethods are used to release a license, increasing the number of available licenses. If there are threads waiting for permission, one of the threads will be awakened.

public synchronized void release() throws InterruptedException {
    while (signals == 0) wait();
    signals--;
    notify();
}

Similarly, usesynchronizedEnsure thread safety and pass after the license is releasednotify()Wake up the thread that may be waiting for.

Example usage

Here's how to use itSimpleSemaphoreA simple example of .

public class Main {
    public static void main(String[] args) {
        SimpleSemaphore semaphore = new SimpleSemaphore(3); // Allow 3 threads to access simultaneously
        Runnable longRunningTask = () -> {
            try {
                ();
                ("Thread " + ().getId() + " is running");
                // Simulate long-term tasks                (2000);
                ();
                ("Thread " + ().getId() + " is finished");
            } catch (InterruptedException e) {
                ();
            }
        };

        for (int i = 0; i < 10; i++) {
            new Thread(longRunningTask).start();
        }
    }
}

In this example, we created a 3 licenseSimpleSemaphore, then 10 threads were started to perform a long-running task. Due to semaphore limitations, these 10 threads will be executed in batches (3 per batch).

Summarize

By usingsynchronizedKeywords,wait()andnotify()Method, we can manually implement a simple semaphore. This implementation provides mutex access and coordination between threads. Although JavaSemaphoreClasses provide more advanced functionality, but manually implementing semaphores is a good exercise in understanding concurrency control. Remember that concurrency tools in the Java standard library should be preferred in real environments because they have been tested more widely and are better optimized.

The above is the detailed content of the method of using the synchronized keyword to implement semaphores. For more information about synchronized semaphores, please pay attention to my other related articles!