August 27, 2019

Part 9: Java Thread Interview Questions & Answers (All About Java Semaphore and Mutex)

Why we need Semaphore?
  • Lets say our application calls a service, which is quite slow. Because the service is slow, at a time only 5 calls can be made.
  • Now lets say their are 50 threads present in the application, and they all try to access the service. We need a mechanism, by which we can restrict the call to slow service. This can be achieved using Semaphore.
  • A Semaphore will act as a layer, with a limited number of permits (in our case permits=5). 
  • Now thread 1 wants to access the service, it will call acquire() method to get the permit. Semaphore will check number of available permits (in our case its 5), if its available it will give permit to thread 1 and then decrements the permit by 1 (now the permit=4).
  • While thread 1 is accessing the slow service, thread 2 comes. The Semaphore again checks available permit (which is 4) and give it to thread 2.
  • Lets say thread 3, 4 and 5 comes and get the permit. While these 5 threads are accessing the slow service thread 6 comes, since now the permit is 0 Semaphore will block the thread 6.
  • In the meanwhile, Thread 1 completes the work from slow service, it will call release() method. The release() method will increment the permit(which was 0) by 1. Now the permit is 1, the Semaphore gives the access to Thread 6 and decrements the permit (new value will be 0).
What is Semaphore in Java?
  • Counting Semaphore is added in Java 5, it acts as a synchronizer which allows to impose a bound on resource.
  • It maintains specified number of pass or permits, in order to access a shared resource, Current Thread must acquire a permit. 
  • If permit is already exhausted by other thread than the thread need to wait until a permit is available. When the thread that acquired the permit completes its job, it releases the permit so that other threads can get it.
  • This concurrency utility can be very useful to implement producer consumer design pattern or implement bounded pool or resources like Thread Pool, DB Connection pool etc.
  • java.util.Semaphore class provides two main method acquire() and release() for getting permits and releasing permits. acquire() method blocks until permit is available. 
  • Semaphore class supports various overloaded version of tryAquire() method which acquires permit from semaphore only if its available during time of call. Where as acquireUninterruptibly() which is a blocking call and wait until a permit is available.
  • Semaphore provides both blocking method as well as unblocking method to acquire permits. 
  • Semaphore can be used to implement better Database connection pool which will block if no more connection is available instead of failing and handover Connection as soon as its available.
  • semaphore.acquire() can throw InterruptedException. If you don't want to handle those exception, you can call semaphore.acquireUninterruptibly().
  • If you want to acquire more than 1 permit, you can use overloaded method which takes int. e.g, if you want 3 permits semaphore.acquireUninterruptibly(3). But make sure the number of permits to take should be equal to number of permits you release, in our case it would be semaphore.release(3). Otherwise, after sometime all the permits will be acquired, because less number of permits are released and program will come to an halt.
  • tryAcquire: Try to acquire, if no permit is available it will not block the thread. The thread will continue doing something else.
  • tryAcquire(timeout): It is same as tryAcquire(), but with a timeout.
  • availablePermits(): It returns the number of available permits.
  • new Semaphone(no_of_permits, fair): no_of_permits is the initial number of permits available.This value may be negative, in which case releases must occur before any acquires will be granted. Where as fair is a boolean value, if set to true semaphore will guarantee first-in first-out granting of permits under contention. i.e It ensures, whichever thread is waiting for the permit for the longest will be given the permit first.
Binary Semaphore
  • A counting semaphore with one permit is known as binary semaphore because it has only two state permit available or permit unavailable. 
  • It can be used to implement mutual exclusion or critical section where only one thread is allowed to execute.
Example:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

final class Task implements Runnable
{
private int taskId;
private Semaphore semaphore;

public Task(int taskId, Semaphore semaphore)
{
this.taskId=taskId;
this.semaphore=semaphore;
}

@Override
public void run() {
System.out.println("Running a thread with name :"+Thread.currentThread().getName()+", for task id:"+this.taskId);
try {
semaphore.acquire();
//call slow service
slowService();
semaphore.release();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}

public void slowService() throws InterruptedException
{
Thread.sleep(100);
}
}

public class SemaphoreTest {

public static void main(String[] args) {
try {
//5 is the number of Permits
Semaphore semaphore= new Semaphore(5);

ExecutorService exeService=Executors.newFixedThreadPool(50);
//IntStream.of(1000).forEach(i->exeService.submit(new Task(i, semaphore)));
for (int i=0; i<100 i="" p=""> {
exeService.submit(new Task(i, semaphore));
}

exeService.shutdown();
exeService.awaitTermination(1, TimeUnit.MINUTES);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}


What is Mutex?
  • Mutex is Mutual Exclusion Object. 
  • It is used to guard shared data such as a linked-list, an array, or any primitive type. 
  • A mutex allows only a single thread to access a resource or critical section.
  • Once a thread acquires a mutex, all other threads attempting to acquire the same mutex are blocked until the first thread releases the mutex. Once released, most implementations arbitrarily (based on some heuristics) chose one of the waiting threads to acquire the mutex and make progress.
  • synchronized keyword is the simplest way to implement a mutex in Java. Every object in Java has an intrinsic lock associated with it. The synchronized method and the synchronized block use this intrinsic lock to restrict the access of the critical section to only one thread at a time. Therefore, when a thread invokes a synchronized method or enters a synchronized block, it automatically acquires the lock. The lock releases when the method or block completes or an exception is thrown from them.
What is the difference between Mutex and Semaphore?

Mutex: There is one toilet, to use the toilet you need a key. Three person are waiting to use the toilet. At a time only one person can occupy the toilet, once he is done, he will give the key to next person.


Semaphore: Let's say we have 4 toilets and each toilet has 4 identical keys. Let's assume 5 people wants to use the toilet, 1st person will come and take the key, then 2nd, 3rd and 4th one. When 5th person comes, he won't get the key. In this case he/she need to wait until toilet is free.
  • Semaphore is a type of signaling mechanism. Mutex is a locking mechanism.
  • Semaphore is an integer variable,  Mutex is just an object.
  • The wait and signal operations can modify a semaphore. Mutex is modified only by the process that may request or release a resource.
  • In Semaphore, if no resource is free, then the process requires a resource that should execute wait operation. It should wait until the count of the semaphore is greater than 0. If Mutex is locked, the process has to wait. The process should be kept in a queue. This needs to be accessed only when the mutex is unlocked.
  • We can have multiple program threads in Semaphore. We can have multiple program threads in mutex but not simultaneously.
  • In Semaphore, value can be changed by any process releasing or obtaining the resource. In Mutex, object lock is released only by the process, which has obtained the lock on it.
  • Types of Semaphore are counting semaphore and binary semaphore. Mutex has no subtypes.
  • Semaphore value is modified using wait () and signal () operation. Mutex object is locked or unlocked.
Can a semaphore act as a mutex?
A semaphore can potentially act as a mutex, if the number of permits it can give out is set to 1 (binary semaphore). However, the most important difference between the two is that in the case of a mutex, the same thread must call acquire and subsequent release on the mutex whereas in the case of a binary semaphore, different threads can call acquire and release on the semaphore.

This leads us to the concept of ownership. A mutex is owned by the thread acquiring it, till the point, it releases it, whereas for a semaphore there’s no notion of ownership.

ALSO CHECKAll About Java Threads

-K Himaanshu Shuklaa..

No comments:

Post a Comment

RSSChomp Blog Directory