Thursday, 3 April 2014

What is Thread collision and how to avoid it in java?

What is Thread Collision?


In a multi-threaded environment, multiple threads will be running in the same method/block of the program. This is called thread collision and it can cause significant effect in the program.  Thread collision leads to race condition.

For example, considered the below program.
The program has a class named ThreadIncrementer ,which implements the Runnable interface. It's run method increments numbers from 1 to 50; And we have created 3 Threads by passing the  runnable object. So each threads will be running the same run method of the ThreadIncrementer class.

Code:
package thread.assignment;

/**
* @author Sivaranjani D
*
*/
public class ThreadIntor {
public static void main(String[] args) throws InterruptedException {
ThreadIncrementer threadIncrementer = new ThreadIncrementer();
Thread t1 = new Thread(threadIncrementer);
Thread t2 = new Thread(threadIncrementer);
Thread t3 = new Thread(threadIncrementer);
t1.start();
t2.start();
t3.start();

t1.join();
t2.join();
t3.join();
System.out.println(threadIncrementer.normalnumber);
}

}

class ThreadIncrementer implements Runnable {
int normalnumber = 0;

public void run() {
for (int i = 0; i < 50; i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
normalnumber++;
}
}
}

Output:
142

The expected output for the above program should be 150. Because the loop will increment normalnumber for 50 and there are 3 threads running. So 3*50 = 150.
But, you don't get the same 150 all the time. That is because of multiple threads collision in the same block.

How Thread collision creates the above problem?


In the above example, take a look at the code normalnumber++. This might look like a single line of code. But it is not.
Generally there are 3 tasks happens inside.

  1. Read the old value of normalnumber

  2. Increment the normalnumber

  3. Reassign the incremented value to normalnumber


Consider now, there 2 threads coming into the block to increment normalnumber. And consider the old value of normalnumber is 5

  • The first thread performs the step 1, and reads the value of normalnumber as 5 and goes to the step 2.

  • Before the first thread increments the value, the second thread also reads the old value of normalnumber as 5.

  • Now, consider the first thread incremented normalnumber to 6 and reassigned the value

  • But since Second Thread also has read the same old value as 5, it will also does the same job what First Thread does.

  • Now we are missing one increment. After 2 increment the value of normalnumber should be 7. Instead we are getting only 6.


In the above program, it may not look serious. But think about the account overdraw by 2 threads, which is a serious issues.

So please make design consideration and follow the below ways to avoid collision in the multi-threaded environment.

Different ways to avoid thread collision:



 

1 comment: