Java Concurrency — Using Semaphores
Access control in concurrency, to understand Semaphore in few words. For instance, you go to a restaurant to have dinner, the restaurant is having tables enough to accommodate 10 families. Hence, only 10 different families (or groups of people) are allowed to have dinner (or food) at a time. The rest will line up in a queue and will wait for their respective turns.
Semaphore is used to enforce such types of restrictions. To provide access to shared resources we use Semaphore, as it helps to synchronous use. Semaphore takes a number as the max permissible permits. For instance,
final int LIMIT =3;
Semaphore semaphore=new Semaphore(LIMIT);
Here’s the list of few semaphore methods that you might need:
- acquire()
- release()
- acquire(permits)
- release(permits)
- availablePermits()
Here is a producer class to provide an implementation to semaphore.
class ProducerImpl implements Runnable {
private final Semaphore semaphore;
private final BlockingQueue<Integer> items;
private final Long SLEEPTIME;
public ProducerImpl(Semaphore semaphore, BlockingQueue<Integer> items, Long sleepTime) {
this.semaphore = semaphore;
this.items = items;
this.SLEEPTIME = sleepTime;
}
@Override
public void run() {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + " acquiring the lock");
try {
semaphore.acquire();
System.out.println(threadName + " gets the lock.\nAvailable locks are: " + semaphore.availablePermits());
for (int i = 0; i < 10; i++) {
items.add(items.size() + 1);
Thread.sleep(SLEEPTIME);
}
System.out.println("The list is " + items);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(threadName + " releasing the lock");
semaphore.release();
}
}
}
This class takes in a queue, number of permits and semaphore itself. Here, run () method is overridden, we request to acquire the lock first so, if there’s any available lock, then access will be granted else it will wait until the permit is acquired.
Simple isn’t it!!!
You can find the complete implementation of the program below:
public class Semaphores {
//max 3 producers will be producing together
public static void main(String[] args) {
final int SIZE = 50;
final int LIMIT = 3;
Semaphore semaphore = new Semaphore(LIMIT);
BlockingQueue<Integer> items = new ArrayBlockingQueue<>(SIZE);
Thread thread1 = new Thread(new ProducerImpl(semaphore, items, 1000L), "Thread A");
Thread thread2 = new Thread(new ProducerImpl(semaphore, items, 2000L), "Thread B");
Thread thread3 = new Thread(new ProducerImpl(semaphore, items, 2000L), "Thread C");
Thread thread4 = new Thread(new ProducerImpl(semaphore, items, 1000L), "Thread D");
Thread thread5 = new Thread(new ProducerImpl(semaphore, items, 2000L), "Thread E");
System.out.println("Starting............");
try {
thread1.start();
thread1.join();
thread2.start();
thread2.join();
thread3.start();
thread4.start();
thread5.start();
thread3.join();
thread4.join();
thread5.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(".....................DONE.....................");
}
}
class ProducerImpl implements Runnable {
private final Semaphore semaphore;
private final BlockingQueue<Integer> items;
private final Long SLEEPTIME;
public ProducerImpl(Semaphore semaphore, BlockingQueue<Integer> items, Long sleepTime) {
this.semaphore = semaphore;
this.items = items;
this.SLEEPTIME = sleepTime;
}
@Override
public void run() {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + " acquiring the lock");
try {
semaphore.acquire();
System.out.println(threadName + " gets the lock.\nAvailable locks are: " + semaphore.availablePermits());
for (int i = 0; i < 10; i++) {
items.add(items.size() + 1);
Thread.sleep(SLEEPTIME);
}
System.out.println("The list is " + items);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(threadName + " releasing the lock");
semaphore.release();
}
}
}
Here’s the output of the above program code:
Post your comments, clap if you like it and queries if you have any.
Till then, happy coding guys!!!