Thread Safety and Code Synchronization in Java
With the advent of Multi core processors, The applications certainly need to be good at Multi threading to utilize the resources. But good care should be taken when designing multi threaded applications where Thread safety should be on top of the agenda for the Designer.
Consider an example – A couple who have a Joint account where both have their ATM cards. They come to different ATMs and try to withdraw some amount at the same time. Now the total balance in the account is 500, Wife tries to withdraw 450 and husband tried to withdraw 100. Both of them were shown the balance as 500. When trying to with draw, the two threads assigned for the transactions try to withdraw the amount. But only one succeeds and other fails. This creates a confusion among the users. This happens because there is no restriction that only one thread is allowed to work on the data at a given time.
Let us consider another example where we have a travel website happybus.com through which you can book your bus tickets.
Now there are only three seats left and two people are trying to book the tickets at the same time. Only one will be able to proceed and other will fail.
If you consider in both the cases, the trouble arises when different threads try to work on the same data at same time.
To avoid this problem, the code synchronization should be implemented which restricts multiple threads to work on the same code at the same time.
Now, Let us see a simple demo of code without thread safety. Given below is the code which demonstrates the Bus reservation example without Thread Safety.
BusReservation .java
package com.mycompany.happybus;
public class BusReservation implements Runnable {
private int totalSeatsAvilable = 2;
@Override
public void run() {
// BusReservation br = new BusReservation();
PassengerThread pt = (PassengerThread) Thread.currentThread();
boolean ticketsBooked = this.bookTickets(pt.getSeatsNeeded(),pt.getName());
if (ticketsBooked == true) {
System.out.println("CONGRATS \t" + Thread.currentThread().getName()+ "..The no of Seats are requested (" + pt.getSeatsNeeded()+ ") are Booked");
} else {
System.out.println("Sorry Mr. " + Thread.currentThread().getName()+ "..The no of Seats are requested (" + pt.getSeatsNeeded()+ ") are Not avilable");
}
}
public boolean bookTickets(int seats, String name) {
System.out.println("Welcome to HappyBus "+ Thread.currentThread().getName()+ "\t No of tickets Avilable are :"+ this.getTotalSeatsAvilable());
if (seats> this.getTotalSeatsAvilable()) {
return false;
} else {
totalSeatsAvilable = totalSeatsAvilable - seats;
return true;
}
}
private int getTotalSeatsAvilable() {
return totalSeatsAvilable;
}
}
PaessengerThread.java
package com.mycompany.happybus;
public class PassengerThread extends Thread {
private int seatsNeeded ;
public PassengerThread(int seats ,Runnable target , String name)
{
super(target,name);
this.seatsNeeded = seats;
}
public int getSeatsNeeded()
{
return seatsNeeded;
}
}
HappyBus.java
package com.mycompany.happybus;
public class HappyBus {
public static void main(String[] args) {
BusReservation br = new BusReservation();
PassengerThread pt1 = new PassengerThread(2, br, "BADRI");
PassengerThread pt2 = new PassengerThread(2, br, "JACK");
pt1.start();
pt2.start();
}
}
Output :
Welcome to HappyBus BADRI No of tickets Avilable are :2
CONGRATS BADRI..The no of Seats are requested (2) are Booked
Welcome to HappyBus JACK No of tickets Avilable are :0
Sorry Mr. JACK..The no of Seats are requested (2) are Not avilable
In the above output, you can see that both user have got the number of tickets available as 2. But when the second user thread tried, the sorry message came out as the first user thread was able to successfully block the ticket.
This kind of code behavior creates confusion in users and can have adverse effects in the data consistency. To avoid these situation it is important to restrict the threads to act in queue. Code synchronization helps to restrict the multiple thread access for a particular part of the code.
Code Synchronization:
Why there is only a single lock per object?
I have two methods – Book tickets and cancel tickets. Both of them work on the same data – Total tickets.
Now when two threads at the same time work on these two methods, they will be able to work on the same data at the same time. So, considering the data manipulation, the locks were implemented on the object level instead of method level.
if this need an example as above same example just we need to change method bookTickets with synchronized method with all classes sample code.
public synchronized boolean bookTickets(int seats, String name) {
System.out.println("Welcome to HappyBus "+ Thread.currentThread().getName()+ "\t No of tickets Avilable are :"+ this.getTotalSeatsAvilable());
if (seats> this.getTotalSeatsAvilable()) {
return false;
} else {
totalSeatsAvilable = totalSeatsAvilable - seats;
return true;
}
Let us consider another example where we have a travel website happybus.com through which you can book your bus tickets.
Now there are only three seats left and two people are trying to book the tickets at the same time. Only one will be able to proceed and other will fail.
If you consider in both the cases, the trouble arises when different threads try to work on the same data at same time.
To avoid this problem, the code synchronization should be implemented which restricts multiple threads to work on the same code at the same time.
Now, Let us see a simple demo of code without thread safety. Given below is the code which demonstrates the Bus reservation example without Thread Safety.
BusReservation .java
package com.mycompany.happybus;
public class BusReservation implements Runnable {
private int totalSeatsAvilable = 2;
@Override
public void run() {
// BusReservation br = new BusReservation();
PassengerThread pt = (PassengerThread) Thread.currentThread();
boolean ticketsBooked = this.bookTickets(pt.getSeatsNeeded(),pt.getName());
if (ticketsBooked == true) {
System.out.println("CONGRATS \t" + Thread.currentThread().getName()+ "..The no of Seats are requested (" + pt.getSeatsNeeded()+ ") are Booked");
} else {
System.out.println("Sorry Mr. " + Thread.currentThread().getName()+ "..The no of Seats are requested (" + pt.getSeatsNeeded()+ ") are Not avilable");
}
}
public boolean bookTickets(int seats, String name) {
System.out.println("Welcome to HappyBus "+ Thread.currentThread().getName()+ "\t No of tickets Avilable are :"+ this.getTotalSeatsAvilable());
if (seats> this.getTotalSeatsAvilable()) {
return false;
} else {
totalSeatsAvilable = totalSeatsAvilable - seats;
return true;
}
}
private int getTotalSeatsAvilable() {
return totalSeatsAvilable;
}
}
PaessengerThread.java
package com.mycompany.happybus;
public class PassengerThread extends Thread {
private int seatsNeeded ;
public PassengerThread(int seats ,Runnable target , String name)
{
super(target,name);
this.seatsNeeded = seats;
}
public int getSeatsNeeded()
{
return seatsNeeded;
}
}
HappyBus.java
package com.mycompany.happybus;
public class HappyBus {
public static void main(String[] args) {
BusReservation br = new BusReservation();
PassengerThread pt1 = new PassengerThread(2, br, "BADRI");
PassengerThread pt2 = new PassengerThread(2, br, "JACK");
pt1.start();
pt2.start();
}
}
Output :
Welcome to HappyBus BADRI No of tickets Avilable are :2
CONGRATS BADRI..The no of Seats are requested (2) are Booked
Welcome to HappyBus JACK No of tickets Avilable are :0
Sorry Mr. JACK..The no of Seats are requested (2) are Not avilable
In the above output, you can see that both user have got the number of tickets available as 2. But when the second user thread tried, the sorry message came out as the first user thread was able to successfully block the ticket.
This kind of code behavior creates confusion in users and can have adverse effects in the data consistency. To avoid these situation it is important to restrict the threads to act in queue. Code synchronization helps to restrict the multiple thread access for a particular part of the code.
Code Synchronization:
Code Synchronization helps in preventing threads working on the same code at the same time. The synchronization works based on the locking concept.
Threads that work on the synchronized code should acquire the lock of the object or class file respectively.
Please remember and important point that there is only one lock per object or loaded class file.
Synchronization can only be applied for method or block of code. But not for classes or variables.
Threads that work on the synchronized code should acquire the lock of the object or class file respectively.
Please remember and important point that there is only one lock per object or loaded class file.
Synchronization can only be applied for method or block of code. But not for classes or variables.
Syntax:
public synchronize void method(){ }
public static synchronize void method{…}
synchronize(this){…}
Threads and Object locks – Behavior
public synchronize void method(){ }
public static synchronize void method{…}
synchronize(this){…}
Threads and Object locks – Behavior
Now let me explain in detail how Objects locks work and avoid different threads to stop executing the same code.,
I have four objects here . Obj1, Obj2, Obj 3, Obj4. Each has different methods and the methods marked with s are synchronized.
Now consider we have two threads, Thread 1 and Thread 2 Both trying to access different methods on ObJ1 Which in turn connect to different method of other objects.
Consider that both threads are started together and let us see the Thread one execution.
When T1 come to M1 in Object 1, It sees that this method is synchronized and it acquires the lock of Obj1.
From Obj1 M1 method, the calls are going to other methods and in this process, the thread acquires locks of different threads. The locks are given in the lock board of thread 1.
On the other side, the Thread 2 trying to access M2 on Obj1 is waiting for the lock of Obj1 to be released by thread 1. Even though both are executing different methods, you should remember that because there is only one lock per object, there no other go for Thread 2 but to wait till lock is released by thread 1.
This is most important concept you have to remember.
To give a good real life example to match thread locking, it is like obtaining locks for a hotel room by a customer. If another customer want to occupy the same room, he needs to wait for the room lock to be returned.
Now consider we have two threads, Thread 1 and Thread 2 Both trying to access different methods on ObJ1 Which in turn connect to different method of other objects.
Consider that both threads are started together and let us see the Thread one execution.
When T1 come to M1 in Object 1, It sees that this method is synchronized and it acquires the lock of Obj1.
From Obj1 M1 method, the calls are going to other methods and in this process, the thread acquires locks of different threads. The locks are given in the lock board of thread 1.
On the other side, the Thread 2 trying to access M2 on Obj1 is waiting for the lock of Obj1 to be released by thread 1. Even though both are executing different methods, you should remember that because there is only one lock per object, there no other go for Thread 2 but to wait till lock is released by thread 1.
This is most important concept you have to remember.
To give a good real life example to match thread locking, it is like obtaining locks for a hotel room by a customer. If another customer want to occupy the same room, he needs to wait for the room lock to be returned.
I think a question might be popping in your mind that why they have allowed only one lock per object. What is the issue even if threads are accessing different methods?

I have two methods – Book tickets and cancel tickets. Both of them work on the same data – Total tickets.
Now when two threads at the same time work on these two methods, they will be able to work on the same data at the same time. So, considering the data manipulation, the locks were implemented on the object level instead of method level.
if this need an example as above same example just we need to change method bookTickets with synchronized method with all classes sample code.
public synchronized boolean bookTickets(int seats, String name) {
System.out.println("Welcome to HappyBus "+ Thread.currentThread().getName()+ "\t No of tickets Avilable are :"+ this.getTotalSeatsAvilable());
if (seats> this.getTotalSeatsAvilable()) {
return false;
} else {
totalSeatsAvilable = totalSeatsAvilable - seats;
return true;
}
Thanks for sharing this informative content , Great work
ReplyDeleteLeanpitch provides online training in Agile coach during this lockdown period everyone can use it wisely.
Certified agile coaching Bangalore
Thanks for sharing this informative content , Great work
ReplyDeleteCreative Thinking for creating an impact!
Product Thinking Community introduces PT Labs powered by Leanpitch
Product thinking conference
Thanks for sharing this informative content , Great work
ReplyDeleteTo crack scrum master interview : Scrum Master Interview Questions
Thanks for sharing this informative content , Great work
ReplyDeleteLeanpitch provides online training in ICP CAT during this lockdown period everyone can use it wisely.
ICP-CAT certification
Thanks for sharing this informative content , Great work
ReplyDeleteLeanpitch provides online training in Product Management Launchpad during this lockdown period everyone can use it wisely.
Product Management Workshop