Concurrency in Java

Introduction

New to Threading ? Click Here to go to  basics

Concurrency in Java

Concurrency is an  issue facing in any  multi-threaded environment .If we are using multiple threads  in a java process , then we need to ensure thread safety for each objects.In simple words , if  multiple threads are accessing  same piece of data and trying to change the same at a time , it will be a problem . Fortunately , Java provides a mechanism to overcome this issue . There is a ‘synchronized‘ keyword in Java provides the solution for this problem. By using this technique , each thread gets lock on a particular object  and after getting the lock that thread is manipulating on that object.By that time other threads trying to access the same object needs to wait till the current thread releases the lock  on that object. JVM is doing is the lock allocation mechanism. After the lock is released from one thread , the lock will be allocated to the  waiting thread. If there are multiple threads waiting , then lock will be allotted on basis of priority.

1)Synchronized non-static methods

Now let us see how  synchronized key word is working. Let us discuss with an example. Here we are defining a class NumericCounter.java. It has a method  countNumbers() . Here we specified it as synchronized , that means only one thread can access the method of  the current object  at a time. If a second  thread is also trying to  access the same method of the same NumericCounter object , it needs to wait to get the lock on that particular object.if the second thread is trying to execute the method using another NumericCounter object , then it will be executed.Once a thread acquires lock on a particular object ,  no other threads can execute any of the synchronized methods of that  class on that object.

/**
* User: Bijoy
* Date: 12/20/12
* Time: 8:16 PM
*/
public class NumericCounter {
public NumericCounter() {

}
public synchronized void countNumbers() {
System.out.println("Now this method is locked by thread :"+Thread.currentThread().getName());
int count = 0;
while (count < 50) { try { System.out.println("Current thread : " + Thread.currentThread().getName() + "; Count = " + count); count = count + 5; Thread.sleep(1000); } catch (InterruptedException ie) { ie.printStackTrace(); } } System.out.println("Lock is going to be released for thread :"+Thread.currentThread().getName()); } }

Now let us see the main class to run the NumericCounter class , SynchSample.java .

public class SynchSample implements Runnable {
private NumericCounter counter = null;
public SynchSample(NumericCounter counter) {
this.counter = counter;
}

public void run() {
counter.countNumbers();
}
public static void main(String[] args) {
NumericCounter counter = new NumericCounter();
SynchSample firstInstance = new SynchSample(counter);
SynchSample secondInstance = new SynchSample(counter);
Thread firstThread = new Thread(firstInstance, "firstThread");
Thread secondThread = new Thread(secondInstance, "secondThread");
firstThread.start();
secondThread.start();
}
}

It is implementing Runnble interface. In the run method we are calling the countNumbers() method . Now two instances of  SynchSample is creating using the same NumericCounter object.Since the SynchSample is implementing the Runnable interface, the SynchSample objects will be Runnables too .Now we can create two threads using two runnable instances.Two threads are named as firstThread and secondThread .Now start both the threads.As of our assumption  one thread needs to get the lock on the object.After that thread is released from that lock , then the second thread gets its lock on the object.So either 'firstThread' or 'secondThread' acquires lock on NumericCounter object after releasing the lock the second one will get the lock on the same.

Now let us verify the output . In my environment 'firstThread' attained the lock first.Then 'secondThread' got the lock . The order may be different  in your case. In any case we can verify the locking mechanism.

Output

Now this method is locked  by thread :firstThread

Current thread : firstThread; Count = 0

Current thread : firstThread; Count = 5

Current thread : firstThread; Count = 10

Current thread : firstThread; Count = 15

Current thread : firstThread; Count = 20

Current thread : firstThread; Count = 25

Current thread : firstThread; Count = 30

Current thread : firstThread; Count = 35

Current thread : firstThread; Count = 40

Current thread : firstThread; Count = 45

Lock is going to be released for thread :firstThread

Now this method is locked  by thread :secondThread

Current thread : secondThread; Count = 0

Current thread : secondThread; Count = 5

Current thread : secondThread; Count = 10

Current thread : secondThread; Count = 15

Current thread : secondThread; Count = 20

Current thread : secondThread; Count = 25

Current thread : secondThread; Count = 30

Current thread : secondThread; Count = 35

Current thread : secondThread; Count = 40

Current thread : secondThread; Count = 45

Lock is going to be released for thread :secondThread

Now let us see what happens if two threads calls the same method on different objects. In this case the SynchSample class will be having two NumericCounter objects . And two threads are creating, they are not sharing the same NumericCounter object.They are having different NumericCounter objects. Now two threads can execute the  countNumbers() in parallel.

public class SynchSample implements Runnable {
private NumericCounter counter = null;

public SynchSample(NumericCounter counter) {
this.counter = counter;
}

public void run() {
counter.countNumbers();
}

public static void main(String[] args) {
NumericCounter counterFirst = new NumericCounter();
NumericCounter counterSecond = new NumericCounter();
SynchSample firstInstance = new SynchSample(counterFirst);
SynchSample secondInstance = new SynchSample(counterSecond);
Thread firstThread = new Thread(firstInstance, "firstThread");
Thread secondThread = new Thread(secondInstance, "secondThread");
firstThread.start();
secondThread.start();
}
}

Now let us verify the output.The output may be different in different environments . But it can give a correct idea.

Outout

Now this method is locked  by thread :firstThread

Current thread : firstThread; Count = 0

Now this method is locked  by thread :secondThread

Current thread : secondThread; Count = 0

Current thread : secondThread; Count = 5

Current thread : firstThread; Count = 5

Current thread : firstThread; Count = 10

Current thread : secondThread; Count = 10

Current thread : firstThread; Count = 15

Current thread : secondThread; Count = 15

Current thread : secondThread; Count = 20

Current thread : firstThread; Count = 20

Current thread : firstThread; Count = 25

Current thread : secondThread; Count = 25

Current thread : secondThread; Count = 30

Current thread : firstThread; Count = 30

Current thread : firstThread; Count = 35

Current thread : secondThread; Count = 35

Current thread : firstThread; Count = 40

Current thread : secondThread; Count = 40

Current thread : firstThread; Count = 45

Current thread : secondThread; Count = 45

Lock is going to be released for thread :firstThread

Lock is going to be released for thread :secondThread

2)Synchronized static methods

A non static synchronized method of a class can be executed by multiple threads at a time on different objects. That the above example showed us. But if we specify a method as static and is synchronized then , in any way only one thread can execute it at a time . It means the lock is not on individual objects , but it is on the class object .

The above explained classes can be modified for verifying the result.

public class NumericCounter {
public NumericCounter() {

}
public static synchronized void countNumbers() {
System.out.println("Now this method is locked by thread :"+Thread.currentThread().getName());
int count = 0;
while (count < 50) { try { System.out.println("Current thread : " + Thread.currentThread().getName() + "; Count = " + count); count = count + 5; Thread.sleep(1000); } catch (InterruptedException ie) { ie.printStackTrace(); } } System.out.println("Lock is going to be released for thread :"+Thread.currentThread().getName()); } }

The main class is  given below.

public class SynchSample implements Runnable {
private NumericCounter counter = null;
public SynchSample(NumericCounter counter) {
this.counter = counter;
}
public void run() {
counter.countNumbers();
}
public static void main(String[] args) {
NumericCounter counterFirst = new NumericCounter();
NumericCounter counterSecond = new NumericCounter();
SynchSample firstInstance = new SynchSample(counterFirst);
SynchSample secondInstance = new SynchSample(counterSecond);
Thread firstThread = new Thread(firstInstance, "firstThread");
Thread secondThread = new Thread(secondInstance, "secondThread");
firstThread.start();
secondThread.start();
}
}

Now let us verify the output.

Output

Now this method is locked  by thread :firstThread

Current thread : firstThread; Count = 0

Current thread : firstThread; Count = 5

Current thread : firstThread; Count = 10

Current thread : firstThread; Count = 15

Current thread : firstThread; Count = 20

Current thread : firstThread; Count = 25

Current thread : firstThread; Count = 30

Current thread : firstThread; Count = 35

Current thread : firstThread; Count = 40

Current thread : firstThread; Count = 45

Lock is going to be released for thread :firstThread

Now this method is locked  by thread :secondThread

Current thread : secondThread; Count = 0

Current thread : secondThread; Count = 5

Current thread : secondThread; Count = 10

Current thread : secondThread; Count = 15

Current thread : secondThread; Count = 20

Current thread : secondThread; Count = 25

Current thread : secondThread; Count = 30

Current thread : secondThread; Count = 35

Current thread : secondThread; Count = 40

Current thread : secondThread; Count = 45

Lock is going to be released for thread :secondThread

3)synchronized block

We can write a certain piece of code in a synchronized block . Like

synchronized(emp){

//some piece of code

                               }

where emp is an  object . Here the code will be executed only when lock on object emp is achieved by the calling thread. let us verify the result by an example we can reuse the same code explained earlier.

public class NumericCounter {
public NumericCounter() {

}
public void countNumbers() {
synchronized (this){
System.out.println("Now this method is locked by thread :"+Thread.currentThread().getName());
int count = 0;
while (count < 50) { try { System.out.println("Current thread : " + Thread.currentThread().getName() + "; Count = " + count); count = count + 5; Thread.sleep(1000); } catch (InterruptedException ie) { ie.printStackTrace(); } } System.out.println("Lock is going to be released for thread :"+Thread.currentThread().getName()); } } }

Here inside the countNumbers() method , we put a synchronized block. That means to execute that block lock on the current NumericCounter object .To verify the result two threads must use the same NumericCounter object.

Now let us see the main class .

public class SynchSample implements Runnable {
private NumericCounter counter = null;
public SynchSample(NumericCounter counter) {
this.counter = counter;
}
public void run() {
counter.countNumbers();
}
public static void main(String[] args) {
NumericCounter counterFirst = new NumericCounter();
SynchSample firstInstance = new SynchSample(counterFirst);
SynchSample secondInstance = new SynchSample(counterFirst);
Thread firstThread = new Thread(firstInstance, "firstThread");
Thread secondThread = new Thread(secondInstance, "secondThread");
firstThread.start();
secondThread.start();
}
}

Output

Now this method is locked  by thread :firstThread

Current thread : firstThread; Count = 0

Current thread : firstThread; Count = 5

Current thread : firstThread; Count = 10

Current thread : firstThread; Count = 15

Current thread : firstThread; Count = 20

Current thread : firstThread; Count = 25

Current thread : firstThread; Count = 30

Current thread : firstThread; Count = 35

Current thread : firstThread; Count = 40

Current thread : firstThread; Count = 45

Lock is going to be released for thread :firstThread

Now this method is locked  by thread :secondThread

Current thread : secondThread; Count = 0

Current thread : secondThread; Count = 5

Current thread : secondThread; Count = 10

Current thread : secondThread; Count = 15

Current thread : secondThread; Count = 20

Current thread : secondThread; Count = 25

Current thread : secondThread; Count = 30

Current thread : secondThread; Count = 35

Current thread : secondThread; Count = 40

Current thread : secondThread; Count = 45

Lock is going to be released for thread :secondThread

Volatile keyword in Java

If we are specifying a variable as volatile then that variable is not storing in the cache . Instead it is storing in the main memory.So if multiple threads are using the variable all those theads are getting the updated value of the variable.

Want to know about thread deadlock issue ?Click here

See Related Discussions

Threading Basics

Communication between threads in Java

Thread Priorities

Join() method in Multit-Threading

The yield() method

The sleep() method

Daemon Threads in Java

Thread pool executor in java

Thread pools in Java

Thread Dead lock in Java

Thread Live lock in Java

3 thoughts on “Concurrency in Java

  1. Pingback: Communication between threads in Java | CoderPanda

  2. Lathish Reply

    Really nice article on Thread.. Not everyone can explain this concept clearly.
    Good job.. 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *