Semaphores

Semaphores are a really simple concept, invented by the famous Dutch computer scientist Edsger Dijkstra.

Basically a semaphore is a counter (integer) that allows a thread to get into a critical region.
What the counter is counting are permits that allow access to the shared resource. Thus, to access the resource, a thread must be granted a permit from the semaphore.

If the value of the counter is greater than 0 then thread get the permit otherwise waits for the permit.
Once thread leaves the critical region increments the counter so that other thread can access the critical section.

Most of the time we use semaphores to limit the number of concurrent threads accessing a specific resource.

Example
let consider, We want to limit connections to some resources to some max limit.Similar to connection pool.
In below example 10 threads are trying to get connection at same time.But we should not allow more than 5 connections

Semaphore Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package com.nirajsonawane;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.stream.IntStream;

class ConnectionPool {

private Semaphore connectionSemaphore;

public ConnectionPool(int poolsize) {
this.connectionSemaphore = new Semaphore(poolsize);
}

public void getConnectionFromPool() {
if (connectionSemaphore.availablePermits() > 0) {
connectionSemaphore.tryAcquire();
System.out.println("Get the connection");
} else {
System.out.println("Max active connection limit reach!! try again");
}
}
public void releaseConnection()
{
connectionSemaphore.release();
}
}
class ConnectionService implements Runnable {

private ConnectionPool connectionPool;
public ConnectionService(ConnectionPool connectionPool) {
this.connectionPool = connectionPool;
}

@Override
public void run() {
connectionPool.getConnectionFromPool();
}
}
public class Semaphores {

public static void main(String[] args) {

ExecutorService executorService = Executors.newFixedThreadPool(10);
ConnectionPool connectionPool = new ConnectionPool(5);
ConnectionService service = new ConnectionService(connectionPool);
IntStream.range(0, 10)
.forEach((cnt) -> executorService.execute(service));
}
}
}

Out of 10 threds only 5 was able to get the connection.

Key Points

  1. tryAcquire()– Return true if a permit is available immediately and acquire it otherwise return false,
  2. acquire()- Acquires a permit and blocking until one is available.
  3. release() – Release a permit
  4. availablePermits() – Return number of current permits available
Share Comments