How to Prevent Race Conditions in Java 8

  • google plus

In Brief...

A race condition occurs in programming when two or more execution threads modify a shared, or critical, resource. Race conditions can result in run time errors that are difficult to isolate and to repair. The term "race" is used because the threads can be regarded as racing each other to complete operations on a variable or other shared resource.

In Java 8, race conditions can be prevented by enforcing single threading through methods that modify shared resources. To learn how to prevent race conditions in Java 8, follow these eight steps.

Take our Introduction to Java Training course for free.

See the Course Outline and Register

Instructions

  1. Open your text editor and create the Java program that will demonstrate the race condition. Type in the following Java statements:
  2. public class PreventRaceConditions implements Runnable {
    	private int inventory=1;
    	long twoSeconds=2000;
    	public static void main (String[] args) {
    		PreventRaceConditions prc=new PreventRaceConditions();
    		Thread firstThread=new Thread(prc, "First thread");
    		Thread secondThread=new Thread(prc, "Second thread");
    		firstThread.start();
    		secondThread.start();
    	}
    	public void run() {
    		if (inventory > 0) {
    			try {
    				System.out.println("Thread " + Thread.currentThread().getName() + " starting with inventory: " + inventory);
    				Thread.sleep(twoSeconds);
    			}
    			catch (InterruptedException e) {
    					// no op
    			}	
    			inventory--;
    			System.out.println("Thread " + Thread.currentThread().getName() + " leaving with inventory: " + inventory);
    		}
    		else {
    			System.out.println("Need to backorder! Thread " + Thread.currentThread().getName() + " found inventory with: " + inventory);
    		}
    	}	
    }

    The program defines an inventory count for an item in our inventory. The variable will serve as our shared resource. The variable is initialized to a value of 1. The program will process orders for this item given that at least one item is present in our inventory. To create a race condition for this critical resource, two threads will be started. Each thread will check the inventory count to ensure that an order can be filled. If the order can be filled then the inventory count will be decremented. If not, then the program indicates that item should be back-ordered. Each thread will be paused 2 seconds so that the other thread can execute. By doing so we are simulating a real world multi-threaded environment.

    The problem occurs when a thread checks the inventory count and decides the order can be filled but is then swapped out, allowing another thread to execute the run method. The second thread will also decide that the order can be filled when in fact the first thread will soon decrement the inventory count, putting this item out of stock.

    You will compile and run the program so that you witness the race condition. Then you will edit the program to fix the race condition.

  3. Save your file as PreventRaceConditions.java.
  4. Open a command prompt and navigate to the directory containing your new Java program. Then type in the command to compile the source and hit Enter.
    Compile Program with Race Condition
  5. You are ready to test your Java program. Type in the command to run the Java runtime launcher and hit Enter.
    Run Program with Race Condition
    Notice that each thread determined that the inventory count was greater than 0 and therefore the order could be filled. But upon leaving the method, each thread displays an inventory count of -1. Obviously, an order cannot be shipped with 0 items and the operation should not be attempted in the first place. The problem is caused by a race condition. In the next step, you will modify the program to eliminate the race condition.
  6. Return to your edit session. You will add two statements to the program to solve the race condition. I have highlighted the statements you need to add to the program in the image below:
    Java Source for Race Condition
    The synchronized keyword declares that only one thread can execute the code contained within the block that is delimited by the curly braces. The this keyword indicates that a lock will be placed on the object instance while a thread controls execution of the statements in the block.
  7. Save your changes.
  8. In the command prompt, type in the command to compile the source and hit Enter.
    Compile Program with Race Condition
  9. You are ready to test your changes. Type in the command to run the Java runtime launcher and hit Enter.
    Run Program with Race Condition
    The first thread successfully fills the order and decrements the inventory count by 1, setting the count to 0. The second thread detects that the inventory count is 0 and cancels the operation with a request to back-order the item.

Author: Stephen Withrow

Stephen has over 30 years' experience in training, development, and consulting in a variety of technology areas including Java, C, C++, XML, JavaScript, AJAX, Tomcat, JBoss, Oracle, and DB2. His background includes design and implementation of business solutions on client/server, Web, and enterprise platforms. Stephen is a published writer in both technical and non-technical endeavors. Stephen received an undergraduate degree in Computer Science and Physics from Florida State University.

Discuss