Inteview Question and Answer on Threading

What is race condition in java

A race condition is a situation in which two or more threads or processes are reading or writing some shared data and their is no proper synchronization which result in unexpected output.Therefore, the result of the change in data is dependent on the thread scheduling algorithm, i.e. both threads are “racing” to access/change the data.

Give an example of Race Condition.

Classical example of Race condition is incrementing a counter since increment is not an atomic operation and can be further divided into three steps like read, update and write. if two threads tries to increment count at same time and if they read same value because of interleaving of read operation of one thread to update operation of another thread, one count will be lost when one thread overwrite increment done by other thread. atomic operations are not subject to race conditions because those operation cannot be interleaved.

How to Identify Race Condition ?

Finding Race conditions in any language is most difficult job and Java is no different, though since readability of Java code is very good and synchronized constructs are well defined heaps to find race conditions by code review. finding race conditions by unit testing is not reliable due to random nature of race conditions. since race conditions surfaces only some time your unit test may passed without facing any race condition. only sure shot way to find race condition is reviewing code manually or using code review tools which can alert you on potential race conditions based on code pattern and use of synchronization in Java.

Two code patterns namely “check and act” and “read modify write” can suffer race condition if not synchronized properly. both cases rely on natural assumption that a single line of code will be atomic and execute in one shot which is wrong e.g. ++ is not atomic.

“Check and Act” race condition pattern :

One classical example of “check and act” race condition in Java is getInstance() method of Singleton Class

getInstace() method first check for whether instance is null and than initialized the instance and return to caller. Whole purpose of Singleton is that getInstance should always return same instance of Singleton. if you call getInstance() method from two thread simultaneously its possible that while one thread is initializing singleton after null check, another thread sees value of _instance reference variable as null (quite possible in java) especially if your object takes longer time to initialize and enters into critical section which eventually results in getInstance() returning two separate instance of Singleton. This may not happen always because a fraction of delay may result in value of _instance updated in main memory.

public Singleton getInstance(){
if(_instance == null){ //race condition if two threads sees _instance= null
_instance = new Singleton();
}
}

an easy way to fix “check and act” race conditions is to synchronized keyword and enforce locking which will make this operation atomic and guarantees that block or method will only be executed by one thread and result of operation will be visible to all threads once synchronized blocks completed or thread exited form synchronized block.

read-modify-update race conditions :

This is another code pattern in Java which cause race condition, classical example is the non thread safe counter.read-modify-update pattern also comes due to improper synchronization of non-atomic operations or combination of two individual atomic operations which is not atomic together e.g. put if absent scenario. consider below code

if(!hashtable.contains(key)){
hashtable.put(key,value);
}

here we only insert object into hashtable if its not already there. point is both contains() and put() are atomic but still this code can result in race condition since both operation together is not atomic. consider thread T1 checks for conditions and goes inside if block now CPU is switched from T1 to thread T2 which also checks condition and goes inside if block. now we have two thread inside if block which result in either T1 overwriting T2 value or vice-versa based on which thread has CPU for execution. In order to fix this race condition in Java you need to wrap this code inside synchronized block which makes them atomic together because no thread can go inside synchronized block if one thread is already there.

Example :

The most basic example to describe a Race condition is a Counter class that increments value of an instance variable .

class Counter {
private int c = 0;

public void increment() {
c++;
}
}

Note :
It seems that the increment operation is atomic ( Atomic operations can’t be interleaved by threads ) but it is not . It can further be divided into three steps :
1. Read the value c.
2. Increment the value .
3. Write the incremented value.

Lets imagine that two threads A and B increments the value of instance variable c . Ideally if there is no interleaving of thread’s operations , the value of the variable should be 2 as both the threads increment it by 1 . Lets see one of the possible scenario where thread’s operations interleave

Thread A : Read c ( which is 0 ).
Thread B : Read c ( Still 0 ).
Thread A : Increments the value by 1.
Thread A : Write the value ( Now c is 1 )
Threab B : Increments the value
Thread B : Write the value ( Still c is 1 )

Here we can see that due to interleaving of Read operations of two threads , the final value of the variable c is 1 and not 2.

What are differences between wait(),sleep() and yeild() method in java?

sleep() and yield()

  • Any of three methods which can be used to pause a thread in Java.
    sleep() and yield() methods are defined in thread class while wait() is defined in the Object class. The key difference between wait() and sleep() is that former is used for inter-thread communication while sleep() is used to introduced to pause the current thread for a short duration.
    When a thread calls the wait() method, it releases the monitor or lock it was holding on that object, but when a thread calls the sleep() method, it never releases the monitor even if it is holding.
  • wait for method in Java should be called from synchronized method or block while there is no such requirement for sleep() method.
  • Another difference is Thread.sleep() method is a static method and applies on current thread, while wait() is an instance specific method and only got wake up if some other thread calls notify method on same object.
  • In the case of sleep(), sleeping thread immediately goes to Runnable state after waking up while in the case of wait(), waiting for a thread first acquires the lock and then goes into Runnable state.
  • The wait() method is called on an Object on which the synchronized block is locked, while sleep is called on the Thread.
  • sleep() method throws Interrupted Exception if another thread interrupts a sleeping thread in java.

yield()

  • While yield() just releases the CPU hold by Thread to give another thread an opportunity to run though it’s not guaranteed who will get the CPU. It totally depends upon thread scheduler and it’s even possible that the thread which calls the yield() method gets the CPU again. Hence, it’s not reliable to depend upon yield() method, it’s just on best effort basis.

   

Comments are closed