Race condition in multithreading and it's solution in java


Contents of page :
  • synchronized block / synchronized method
  • Example (Train ticket booking)-
    • Program to show that without synchronization problems will happen when  2 passengers try to book train ticket, dat too when only 1 ticket was available >
  • Now, let’s try to solve the problem by using synchronized block.
    • Program to show that with synchronization no problems will happen when  2 passengers try to book train ticket, dat too when only 1 ticket was available>
  • Now, let’s discuss few sub questions that could be framed>



synchronized block / synchronized method
This is very important question, this forms the core of multi threading, you should be able to explain this question in detail. When more than one thread try to access same resource without synchronization causes race condition.
So we can solve race condition by using either synchronized block or synchronized method. When no two threads can access same resource at a time phenomenon is also called as mutual exclusion.


Example (Train ticket booking)-
Let's say there is only 1 ticket available in train, and two passengers are trying to book that ticket at same time without synchronization.
It might happen that both might end up booking up ticket, though only ticket was available, which is of course going to create problem.
But if synchronization was there only of them would have been able to book ticket.

Program to show that without synchronization problems will happen when  2 passengers try to book train ticket, dat too when only 1 ticket was available >
/** Copyright (c), AnkitMittal JavaMadeSoEasy.com */
class TicketBooking implements Runnable{
   int ticketsAvailable=1;
  
   public void run(){
         
          System.out.println("Waiting to book ticket for : "+Thread.currentThread().getName());
          if(ticketsAvailable>0){
                 System.out.println("Booking ticket for : "+Thread.currentThread().getName());
                
                 //Let's say system takes some time in booking ticket (here we have taken 1 second time)
                 try{
                       Thread.sleep(1000);
                 }catch(Exception e){}
                  
                 ticketsAvailable--;
                 System.out.println("Ticket BOOKED for : "+ Thread.currentThread().getName());
                 System.out.println("currently ticketsAvailable = "+ticketsAvailable);
          }
          else{
                 System.out.println("Ticket NOT BOOKED for : "+ Thread.currentThread().getName());
          }
         
         
   }
  
}
/** Copyright (c), AnkitMittal JavaMadeSoEasy.com */
public class MyClass {
   public static void main(String args[])
   {
          TicketBooking obj=new TicketBooking();
         
          Thread thread1=new Thread(obj,"Passenger1 Thread");
          Thread thread2=new Thread(obj,"Passenger2 Thread");
         
          thread1.start();
          thread2.start();
         
   }
}
/*OUTPUT
Waiting to book ticket for : Passenger1 Thread
Waiting to book ticket for : Passenger2 Thread
Booking ticket for : Passenger1 Thread
Booking ticket for : Passenger2 Thread
Ticket BOOKED for : Passenger1 Thread
currently ticketsAvailable = 0
Ticket BOOKED for : Passenger2 Thread
currently ticketsAvailable = -1
*/
If we note the above program,
first Passenger1 Thread and Passenger2 Thread waited to book tickets.
Than, both threads tried to check the available ticket count and it was 1.
Both threads were able to book ticket.
And ultimately available ticket was reduced to -1, which is practically impossible, tickets count can never dip below 0.
RACE CONDITION PROBLEM : 1 ticket was booked by 2 passengers.

Now, let’s try to solve the problem by using synchronized block.

Program to show that with synchronization no problems will happen when  2 passengers try to book train ticket, dat too when only 1 ticket was available>
class TicketBooking implements Runnable{
   int ticketsAvailable=1;
  
   public void run(){
         
          System.out.println("Waiting to book ticket for : "+Thread.currentThread().getName());
          synchronized (this) {
                 if(ticketsAvailable>0){
                       System.out.println("Booking ticket for : "+Thread.currentThread().getName());
                      
                       //Let's say system takes some time in booking ticket (here we have taken 1 second time)
                       try{
                              Thread.sleep(1000);
                       }catch(Exception e){}
                        
                       ticketsAvailable--;
                       System.out.println("Ticket BOOKED for : "+ Thread.currentThread().getName());
                       System.out.println("currently ticketsAvailable = "+ticketsAvailable);
                 }
                 else{
                       System.out.println("Ticket NOT BOOKED for : "+
                                 Thread.currentThread().getName());
                 }
                
          }//End synchronization block
         
         
   }
  
}
/** Copyright (c), AnkitMittal JavaMadeSoEasy.com */
public class MyClass {
   public static void main(String args[])
   {
          TicketBooking obj=new TicketBooking();
         
          Thread thread1=new Thread(obj,"Passenger1 Thread");
          Thread thread2=new Thread(obj,"Passenger2 Thread");
         
          thread1.start();
          thread2.start();
         
   }
}
/*OUTPUT
Waiting to book ticket for : Passenger2 Thread
Waiting to book ticket for : Passenger1 Thread
Booking ticket for : Passenger2 Thread
Ticket BOOKED for : Passenger2 Thread
currently ticketsAvailable = 0
Ticket NOT BOOKED for : Passenger1 Thread
*/
If we note the above program,
first Passenger1 Thread and Passenger2 Thread waited to book tickets.
Than, Passenger1 Thread entered the synchronized block and acquired object lock, but Passenger2 Thread wasn’t able to acquire object lock and was waiting for Passenger1 Thread to release object lock.
By the time Passenger1 Thread was successfully able to book ticket and reduce the available ticket count to 0, and then release object lock by exiting synchronized block.
Than Passenger2 Thread got a chance to acquire object lock, but available ticket count at that time was 0 so it wasn’t able to book ticket.

RACE CONDITION PROBLEM SOLVED : 1 ticket was booked by only 1 passenger, while other wasn’t able to book any ticket.



Now, let’s discuss few sub questions that could be framed>
What if two threads try to read same resource without synchronization?
When two threads try to read on same resource without synchronization, it’s never going to create any problem.

What if two threads try to write to same resource without synchronization?
When two threads try to write to same resource without synchronization, it’s going to create synchronization problems.






RELATED LINKS>

Volatile keyword vs synchronized>

Volatile keyword in java- difference between synchronized and volatile, 10 key points about volatile keyword, why volatile variables are not cached in memory

Differences between synchronized and volatile keyword in detail


Race Condition >

Race condition in multithreading and it's solution



Consumer Producer problem solution using different techniques >
Solve Consumer Producer problem by using wait() and notify() methods in multithreading



DeadLock and it’s detection >

Deadlock in multithreading - program to form DeadLock, solving DeadLock, measures to avoid Deadlock.


VisualVM - Thread dumps - Generating and analyzing Thread Dumps using VisualVM - step by step detail to setup VisualVM with screenshots


JSTACK - Thread dumps - Generating and analyzing Thread Dumps using JSATCK - step by step detail to setup JSTACK with screenshots


Reason why suspend() and resume() methods are deprecated and Deadlock prone

destroy() method in java - usage, reason why destroy() method is deprecated and Deadlock prone.



Situation based questions -

Suppose you have 2 threads (Thread-1 and Thread-2) on same object. Thread-1 is in synchronized method1(), can Thread-2 enter synchronized method2() at same time?

Suppose you have thread and it is in synchronized method and now can thread enter other static synchronized method from that method?

Suppose you have 2 threads (Thread-1 on object1 and Thread-2 on object2). Thread-1 is in synchronized method1(), can Thread-2 enter synchronized method2() at same time?


eEdit
Must read for you :