Semaphore Introduction
Semaphore is a synchronization primitive that can be used to ensure that only one thread can access a shared resource at any point of time. Semaphore guards critical sections of the code by providing the necessary signalling and prevents any race conditions. Semaphore controls access to shared resources by using counters. If the value of semaphore i.e. counter is greater than zero then it indicates resources are available and a thread can access the shared resource. If the value of semaphore is zero then no resources are available and access is denied.
Semaphores that allow any arbitrary value for the counter is called counting semaphores. Semaphores that allow only values 0 and 1 are called binary semaphores.
Java Semaphore Class
Java supports Semaphore synchronization object that can be used to implement semaphore. Some of the key APIs of Semaphore class are listed below.- Semaphore(int permits) - Constructor that creates a semaphore with the given number of permits.
- Semaphore(int permits, boolean fair) - Constructor that creates a semaphore with the given number of permits and fairness. If fairness is true it is ensured that waiting threads are granted a permit in the order they requested access.
- void acquire() - Acquires one permit. If permit is not granted at the time of call then the invoking thread is suspended.
- void acquire(int permits) - Acquires the specified number of permits.
- void release() - Release a permit back to the semaphore.
- void release(int permits) - Releases specified number of permits back to the semaphore.
Java Semaphore Example
In this example, we create a shared resource i.e. count. There is a producer thread which increments the count. There is a consumer thread which decrements the count. We create a semaphore to synchronize the producer and consumer. Both the threads acquire a permit from the semaphore before executing the critical section. Once completed the thread releases the permit back to the semaphore.package com.sourcetricks.semaphore; import java.util.concurrent.Semaphore; public class SemaphoreExample { // Shared resources to be guarded private static int count = 0; // Producer thread. Counts up the resource. private static class ProducerThread implements Runnable { private Semaphore s = null; ProducerThread(Semaphore s) { this.s = s; } @Override public void run() { try { System.out.println("Producer requesting permit"); s.acquire(); System.out.println("Producer gets permit"); for ( int i = 0; i < 5; i++ ) { count = count + 1; System.out.println("Counting up"); } Thread.sleep(5000); System.out.println("Producer releases permit"); s.release(); } catch (InterruptedException e) { e.printStackTrace(); } } } // Consumer thread. Counts down the resource. private static class ConsumerThread implements Runnable { private Semaphore s = null; ConsumerThread(Semaphore s) { this.s = s; } @Override public void run() { try { System.out.println("Consumer requesting permit"); s.acquire(); System.out.println("Consumer gets permit"); for ( int i = 0; i < 5; i++ ) { count = count - 1; System.out.println("Counting down"); } System.out.println("Consumer releases permit"); s.release(); } catch (InterruptedException e) { e.printStackTrace(); } } } // Main program public static void main(String[] args) { Semaphore semaphore = new Semaphore(1); Thread t1 = new Thread(new ProducerThread(semaphore)); Thread t2 = new Thread(new ConsumerThread(semaphore)); t1.start(); t2.start(); } }This program produces the following output.
Producer requesting permit Consumer requesting permit Producer gets permit Counting up Counting up Counting up Counting up Counting up Producer releases permit Consumer gets permit Counting down Counting down Counting down Counting down Counting down Consumer releases permitRead other concurrency tutorials from Java Tutorials page.
0 comments:
Post a Comment