Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

On Properly Using Volatile and Synchronized

DZone's Guide to

On Properly Using Volatile and Synchronized

Dig into the volatile and synchronized modifiers in Java — when to use which and how they both work — to help broaden your understanding of multithreading.

· Java Zone
Free Resource

Build vs Buy a Data Quality Solution: Which is Best for You? Gain insights on a hybrid approach. Download white paper now!

For the last few weeks, I've been writing about the transient modifier and the different types of references available in Java. I want to focus on underused/misused topics in Java and am bringing you the volatile and synchronized modifiers this week .

Multithreading is an entire discipline that takes years to master and properly understand. I'll provide a short introduction in this article.

In computing, a resource can be accessed from different threads concurrently. This can lead to inconsistency and corrupt data. A thread ThreadA accesses a resource and modifies it. In the meantime, the thread ThreadB starts accessing the same resource. Data may get corrupted since it is concurrently being modified. Let´s analyze an example without any kind of protection:

class PrintDemo {
private int i;
   public void printCount() {

      try {
         for (i = 5; i > 0; i--) {
            System.out.println("Selected number is: "  + i );
         }
      } catch (Exception e) {
         System.out.println("Thread has been interrupted.");
      }
   }
}

class ThreadDemo implements Runnable {
   private Thread thread;
   private String threadName;
   PrintDemo printDemo;

   ThreadDemo(String threadName, PrintDemo printDemo) {
      this.threadName = threadName;
      this.printDemo = printDemo;
   }

   public void run() {
      printDemo.printCount();
      System.out.println("Thread " +  threadName + " finishing.");
   }

   public void start () {
      System.out.println("Starting " +  threadName);
      if (thread == null) {
         thread = new Thread (this, threadName);
         thread.start ();
      }
   }
}

public class Example {
   public static void main(String args[]) {

      PrintDemo printDemo = new PrintDemo();

      ThreadDemo firstThread = new ThreadDemo("Thread 1", printDemo);
      ThreadDemo secondThread = new ThreadDemo("Thread 2", printDemo);

      try {
         firstThread.start();
         secondThread.start();
      } catch( Exception e) {
         System.out.println("Interrupted");
      }
   }
}

Example without synchronized Java


If you execute this command, the result is eclectic and non-deterministic. Each time, you will end up with a different random output. That is because each thread executes in different instants.

Starting Thread 1 output:
Starting Thread 2 output:
Selected number is: 5
Selected number is: 4
Selected number is: 3
Selected number is: 2
Selected number is: 5
Selected number is: 4
Selected number is: 1
Selected number is: 3
Selected number is: 2
Selected number is: 1
Thread Thread 1 finishing.
Thread Thread 2 finishing.


Both modifiers deal with multithreading and protection of code sections from threads accesses. My gut feeling is that synchronized is more widely used and understood than volatile, so I will start my article explaining how it works. We will need it as well later to understand the differences with volatile.

Synchronized Modifier

The synchronized modifier can be applied to a statement block or a method. Synchronized provides protection by ensuring that a crucial section of the code is never executed concurrently by two different threads, ensuring data consistency. Let´s apply the modifier synchronized to the previous example to see how it would be protected:

class PrintDemo {
   public void printCount() {
      try {
         for (int i = 5; i > 0; i--) {
            System.out.println("Selected number is: "  + i );
         }
      } catch (Exception e) {
         System.out.println("Thread has been interrupted.");
      }
   }
}

class ThreadDemo implements Runnable {
   private Thread thread;
   private String threadName;
   PrintDemo printDemo;

   ThreadDemo(String threadName, PrintDemo printDemo) {
      this.threadName = threadName;
      this.printDemo = printDemo;
   }

   public void run() {
  synchronized(printDemo) {
  printDemo.printCount();
  }
      System.out.println("Thread " +  threadName + " finishing.");
   }

   public void start () {
      System.out.println("Starting " +  threadName);
      if (thread == null) {
         thread = new Thread (this, threadName);
         thread.start ();
      }
   }
}

public class Example {
   public static void main(String args[]) {

      PrintDemo printDemo = new PrintDemo();

      ThreadDemo firstThread = new ThreadDemo("Thread 1", printDemo);
      ThreadDemo secondThread = new ThreadDemo("Thread 2", printDemo);

      try {
         firstThread.start();
         secondThread.start();
      } catch( Exception e) {
         System.out.println("Interrupted");
      }
   }
}

Example with synchronized Java


Note that in this example, we have added synchronized to the section where the function printCount() runs. If you execute now this function, the result will always be the same:

Starting Thread 1
Starting Thread 2
Selected number is: 5
Selected number is: 4
Selected number is: 3
Selected number is: 2
Selected number is: 1
Thread Thread 1 finishing.
Selected number is: 5
Selected number is: 4
Selected number is: 3
Selected number is: 2
Selected number is: 1
Thread Thread 2 finishing.


Now that synchronized has been explained, let's take a look at volatile.

Volatile Modifier

We have mentioned before that the synchronized modifier could be applied to blocks and methods. Well, the first difference between synchronized and volatile is that volatile modifiers can be applied to fields.

A small note on how Java memory and multithreading work. When we are working with multithreading environments, each thread creates its own copy on a local cache of the variable that it's dealing with. When this value is being updated, the update happens first in the local cache copy and not in the real variable. Therefore, these threads are agnostic to the values that other threads are changing.

Here volatile changes the paradigm. When a variable is declared as volatile, it will not be stored in the local cache of a thread. Instead, each thread will access the variable in the main memory and other threads will be able to access the updated value. Let's compare all the methods for a proper understanding:

int firstVariable;
int getFirstVariable() {return firstVariable;}

volatile int secondVariable;
int getSecondVariable() {return secondVariable;}

int thirdVariable;
synchronized int getThirdVariable() {return thirdVariable;}


The first method is non-protected. A thread T1 will access the method, create its own local copy of firstVariable, and play with it. In the meantime, T2 and T3 can also access firstVariable and modify its value. T1, T2, and T3 will have their own values of firstVariable, which might not be the same and that have not been copied to the Main memory of Java, where the real results are held.

getSecondVariable(), on the other hand, accesses a variable that has been declared as volatile. That means, each thread is still able to access the method or block since it has not been protected with synchronized, but they will all access the same variable from the main memory, and will not create their own local copy. Each thread will be accessing the same value.

And as we can imagine from the previous examples, getThirdVariable() will only be accessed from one thread at a time. That ensures that the variable will remained synchronized throughout all of the threads executions.

Usefulness of Volatile and Synchronized

After reading this short article, a question will likely pop-up in your mind: I understand the theoretical implications, but what are the practical ones?Synchronized will probably be easier to understand at this point, but when it is useful to apply the volatile modifier? I always like to showcase an example to provide a better understanding.

Think of a Date variable. The Date variable always needs to be the same, seems it updates on a regular pace. Each thread accessing a Date variable that has been declared as volatile will always show the same value.

There are two main aspects regarding thread safety. One is execution control and the other is memory visibility. Whereas volatile provides memory visibility (all threads will access the same value from the main memory) there is no guarantee of execution control, and this latest can only be achieved via synchronized.

Also, in Java all read and write operations will be atomic for a volatile variable (including long and double variables). Many platforms perform the operations in long and double in two steps, writing/reading 32 bytes at a time, and allowing two threads to see two different values. This can be avoided by using volatile.

Thanks Erik Hellman for your code and article review, you rock.

I write my thoughts about Software Engineering and life in general on my Twitter account. If you like this article or if it helps you, feel free to share and/or leave a comment. This is the currency that fuels amateur writers!

Build vs Buy a Data Quality Solution: Which is Best for You? Maintaining high quality data is essential for operational efficiency, meaningful analytics and good long-term customer relationships. But, when dealing with multiple sources of data, data quality becomes complex, so you need to know when you should build a custom data quality tools effort over canned solutions. Download our whitepaper for more insights into a hybrid approach.

Topics:
multithreading ,java ,android ,volatile ,synchronized

Published at DZone with permission of Enrique Lopez Manas, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}