Race conditions


Its been a long time since I posted. Today I am going to talk about race conditions. So lets start off with the basic question, What exactly is a race condition?

“A race condition is an undesirable situation that occurs when a device or system attempts to perform two or more operations at the same time, but because of the nature of the device or system, the operations must be done in the proper sequence in order to be done correctly.”

Lets elaborate on this with an example. Lets have a example of a simple Map which stores name, value pairs for us. This Map is stored centrally and acts as a cache for us. Whenever we want some value we first check teh Map for teh value if found we return the value as is otherwise we create a new value and insert it into our map and return the created value.

 Here is a sample class to achieve the purpose:


public class Cache {

  private Map<String, Object> map = new HashMap<String, Object>();

  public Object getValue(String name) {

    return map.get(name);

  }

  public void putValue(String name, Object value) {

   map.put(name, value);

  }

}

and here is a sample usage:


Cache cache = new Cache();

if ( cache.getValue('test') ) == null ) {

   Object obj = new Object();

   cache.put('test', obj);

}

Quite simple. Is there any possibility of having created two Objects for the value test in our system? If yes then you don’t have to read further you already know what are race conditions but for those of you who aren’t here is the explanation:

Imagin two threads Thread1 and Thread2 running this exact same piece of code. Now both the threads start at the same time. They execution pointer reaches the line 4 where we are querying for an object but since it’s not in the cache both the threads get a null. So they both proceed  furhter and we end up creating two Objects in the system. So here is the problem. Two threads are racing for the same resource and that is why it is called a race condition. So how do we fix up the thing?

You must be thinking that making the methods getValue and putValue synchronized should fix up the issue but it isn’t that simple. Because the correct order for execution invloves two operations. When we had a race condition the order of operation was getValue, getValue, putValue and putValue. The correct order should have been getValue, putValue and then getValue. So how do we do that. Well the simplest solution is to make the block in which we are accessing this shared data synchronized. This is also termed as the critical section. In our case the critical section of our code is from line 4 – 10. Wrapping this inside a synchronized block should fix the problem.


Cache cache = new Cache();

synchronized (this) 

{ 

  if ( cache.getValue('test') ) == null ) {

     Object obj = new Object();

     cache.put('test', obj);

  }

}

 There can be many optimizations that we can do to further improve the solution, more on this later when I talk about the different levels of synchronization that java provides and overheads involved in each one of them. But for now this should be enough to handle the situation.

So as a final thought whenever you have a SHARED resource which can be accessed by m,ultiple threads at the same time always keep the race conditions in mind. These are the simplest of the mistakes that most of the programmers make while coding and these turn out to be the hardest one to fix once the system gets into production. Always keep an eye out for these when coding! Until then happy coding.

Advertisements
Race conditions

4 thoughts on “Race conditions

  1. Victor Louis says:

    i would like to add some more points in you article about race condition.
    Race conditions are among the most common classes of bugs found in deployed software. They are only possible in environments in which there are multiple threads or processes occurring at once that may potentially interact (or some other form of asynchronous processing, such as with UNIX signals). People who have experience with multithread programming have almost certainly had to deal with race conditions, regardless of whether they know the term. Race conditions are a horrible problem because a program that seems to work fine may still harbor them. They are very hard to detect, especially if you’re not looking for them. They are often difficult to fix, even when you are aware of their existence. Race conditions are one of the few places where a seemingly deterministic program can behave in a seriously nondeterministic way. In a world where multithreading, multiprocessing, and distributed computing are becoming more and more prevalent, race conditions will continue to become a bigger and bigger problem. . A good static source code analysis tool like Coverity Prevent will identify any data race it encounters while executing your program, and flag it for you to fix. Coverity has customers like Symbian, RIM (Blackberry), Juniper networks, Cisco, Texas instruments and is also used by the Department of Homeland security to scan lots of open source projects. You can get more info at http://www.Coverity.com

  2. tim says:

    yes, there is a race condition here, but it’s harmless. So what if 2 threads get the null values when call getValue? They will go ahead and put into the map. When inserting a duplicate value into the Map, the Map simply reject it. No big deal. And when calling getValue again, the 2 Thread will assured to get the correct value-pair anyway. There’s a race condition admittely since the Map is a shared resource but it’s harmless here.

  3. faisalferoz says:

    @time: true the race condition is somewhat harmless but also note that in your case you will end up creating two objects. The thing to note is that in some cases the objects are cached because they are expensive to create and having such a race condition in the code can be one of the hardest bugs to reproduce.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s