Header javaperspective.com
JavaPerspective.com  >   Intermediate Tutorials  >   2. Concurrency  >   2.2. What is synchronization?

2.2. What is synchronization?
Last updated: 31 January 2013.

When multiple threads are running concurrently, they may execute the same statements at the same time if those statements belong to an object that is shared by the concurrently running threads. Such a concurrent execution can lead to memory errors. Synchronization is a set of mechanisms you can use to avoid such concurrent access problems by not allowing multiple threads to execute the same statements simultaneously. As an example, consider the class Shared shown below:

public final class Shared {

   
private int[] array = new int[10];

   
public void incrementArrayElements() throws InterruptedException{
         
for(int i=0; i<array.length; ++i){
               
array[i] = array[i] + 1;
                Thread.sleep
(100);
         
}
    }

   
public int[] getArray(){
         
return array;
   
}

}

The class Shared contains a private field named array which is an array of integers, a getter named getArray which returns the value of array and a method named incrementArrayElements which iterates over the array of integers and increments by 1 each of its elements. The execution is paused for 100 milliseconds at each iteration. The class MyThread shown below is a thread that uses an instance of the class Shared:

public final class MyThread extends Thread {

   
private Shared sharedInstance;

   
public MyThread(Shared sharedInstance){
         
this.sharedInstance = sharedInstance;
   
}

   
public void run(){
         
try{
               
sharedInstance.incrementArrayElements();
         
}
         
catch(InterruptedException e){

          }
    }

}

As you can see, no instance of the class Shared is created in the class MyThread. Instead, the constructor of the class MyThread takes an instance of the class Shared. That instance is stored in a private field named sharedInstance and is used in the method run to invoke the method incrementArrayElements.

Finally, the class App shown below contains a main method that creates a single instance of the class Shared named sharedInstance and passes it to two instances of the class MyThread. Consequently, when those two instances are started, they share the same instance of the class Shared. The main method waits for the two threads to die before printing to the standard output the content of the array of integers belonging to sharedInstance:

public final class App {

   
public static void main(String[] args){
         
try{
               
Shared sharedInstance = new Shared();

                Thread thread1 =
new MyThread(sharedInstance);
                Thread thread2 =
new MyThread(sharedInstance);

                thread1.start
();
                thread2.start
();

                thread1.join
();
                thread2.join
();

               
for(int i : sharedInstance.getArray())
                     
System.out.println(i);
         
}
         
catch(InterruptedException e){

          }
    }

}

Since each thread increments by 1 each element of the shared array of integers, you could reasonably expect each array element to be equal to 2 when both threads have died. However, if you run the class App, you may get an output like the following if you're unlucky enough:

2
2
2
2
1
1
2
1
2
2

In the above output, several elements of the array are equal to 1 instead of being equal to 2. The reason is that an array element can be accessed at the same time by both threads before being incremented. In that case, each thread reads the value of the element which is 0, increments it by 1 and stores the result (which is 1) to the memory location of the array element. Hence, the value 1 is stored twice to that memory location.

This example shows how multithreading can lead to memory errors when several threads access shared data at the same time. Synchronization is a Java feature that is meant to avoid such issues by preventing multiple threads to execute the same statements simultaneously. You can apply synchronization to a method or to a block of code within a method.

A synchronized method is a method that cannot be executed at the same time by multiple threads. When multiple theads are to enter a synchronized method, each thread waits for its turn to enter the method, that is, when the thread currently executing the method has finished. As a result, synchronizing methods may slow down the execution of a program and lead to performance problems.

Similarly, a block of critical code that is synchronized can be executed only by a single thread at a time. For performance reasons, synchronizing a block of critical code within a method is a better choice than synchronizing the whole method. Generally, a block of synchronized code is preceded and/or followed by statements that can be executed concurrently.

Synchronizing a method or a block of code and thereby not allowing its execution by multiple threads at a time is also termed mutual exclusion.

The next tutorial will show you how to synchronize a method.


You are here :  JavaPerspective.com  >   Intermediate Tutorials  >   2. Concurrency  >   2.2. What is synchronization?
Next tutorial :  JavaPerspective.com  >   Intermediate Tutorials  >   2. Concurrency  >   2.3. Method synchronization


Copyright © 2013. JavaPerspective.com. All rights reserved.  ( Terms | Contact | About ) 
Java is a trademark of Oracle Corporation
Image 1 Image 2 Image 3 Image 4 Image 5 Image 6 Image 7