Suppose a single thread wants to run a set of statements as a single unit (atomic action) and some other thread trying to disturb it by executing that same set of statements.Can you guess what will be the result??
See the example given below.Here one thread trying to print a statement [Hello] ,simultaneously another thread also trying to do the same thing.Will it work correctly??.Let us check.
public class Main {
public static void main(String[] args) {
MyResource resource = new MyResource();
MyThread t1 = new MyThread(resource);
MyThread t2 = new MyThread(resource);
t1.start();
t2.start();
}
}
class MyThread extends Thread {
MyResource resource;
public MyThread(MyResource resource) {
this.resource = resource;
}
public void run() {
try {
resource.display();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class MyResource {
void display() throws InterruptedException {
//-------------Atomic Action Start----------
System.out.print("[");
Thread.sleep(1000);
System.out.print("HELLO");
Thread.sleep(1000);
System.out.println("]");
//------------Atomic Action End-----------
}
}
The expected result is
[HELLO]
[HELLO]
But the actual result is something like
[[HELLOHELLO]
]
What is the reason for it.Both the threads t1 and t2 trying to execute the MyResource.display() method simultaneously.When one thread goes for sleep another thread executes this method and vice versa.
How can we solve it?.We can use the synchronized method or synchronized block in java to solve this problem.
package p1;
public class Main {
public static void main(String[] args) {
MyResource resource = new MyResource();
MyThread t1 = new MyThread(resource);
MyThread t2 = new MyThread(resource);
t1.start();
t2.start();
}
}
class MyThread extends Thread {
MyResource resource;
public MyThread(MyResource resource) {
this.resource = resource;
}
public void run() {
try {
resource.display();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class MyResource {
synchronized void display() throws InterruptedException {
System.out.print("[");
Thread.sleep(1000);
System.out.print("HELLO");
Thread.sleep(1000);
System.out.println("]");
}
}
Here the expected and the actual result is
[HELLO]
[HELLO]
Consider another real-time example .
void withdrawAmount(int amt)
{
if(balance-amt>=min_balance)
{
balance=balance-amt;
}
}
Suppose Suresh and Harish ,two brothers have a joint account and both have individual ATM cards.If both are trying to withdraw an amount ,will it work correctly?.Consider a scenario ,both of them are trying to withdraw an amount 1000 simultaneously,current balance is 2000 and minimum required balance is 1000.
STEP1:Suresh checks condition(balance-1000>=min_bal) ---->True
STEP2:Harish checks condition(balance-1000>=min_bal) ---->True
STEP3:Suresh withdraws amount-------->balance=1000
STEP4:Harish withdraws amount-------->balance=0 (Invalid Transaction)
What is the problem ?. What is really happened ?.We have to run the check for balance and withdraw as an atomic unit. i.e.
------------------Atomic Action Begins-----------------
STEP1:Suresh checks condition(balance-1000>=min_bal) ---->True
STEP2:Suresh withdraws amount-------->balance=1000
-----------------Atomic Action Begins------------------
-----------------Atomic Action Begins----------------
STEP3:Harish checks condition(balance-1000>=min_bal) ---->False
----------------Atomic Action Begins-----------------
How can we implement it using synchronized in java.
synchronized void withdrawAmount(int amt)
{
{
if(balance-amt>=min_balance)
{
}
All the statements within the synchronized method will act as a single atomic unit.
balance=balance-amt;
}}
All the statements within the synchronized method will act as a single atomic unit.
Simple and Super....Very Userful...
ReplyDeleteThanks,
Muthu Ram.M
Amen.
ReplyDeleteHi radha krishna garu can you please help me in my problem if possible
ReplyDelete/*My problem mainly deals with the synchronization in these example there is professor and two ta's(teaching assistant).Students will comes to the professor in a particular hours for questions on the subject but the professor allows only one person at a time so remaining must wait until the student comes out so professor can clarify the doubts only for 10 student in his office hours so if students are more than 10 they need to go the TA'S .
In these example students are threads and prof and 2 ta's are sharedable resource.synchronization must be used to keep the threads(students )to wait
Thanking you*/
import java.io.*;
import java.util.*;
import java.util.Calender;
public class Synchsema{
public static boolean prof=false; /* default professor, ta1 & ta2 are
public static boolean ta1=false; /* free and they are ready to recieve
public static boolean ta2=false; /* students
public static int student=0;
public static void call() /* Checking the Professor(1st)
{ /* TA1(2nd), TA2(3rd) whether
while(Synchsema.pprof==true) /* they are free or not
{
System.out.println(Thread.currentThread().getName( ) + " Professor is Busy");
if(Synchsema.ta1==true)
{
if(Synchsema.ta2==true) /* if they are not free
{ /* student has to wait
System.out.println(Thread.currentThread().getName( ) + " Ta1 & Ta2 is Busy"); /* for some time(sleep)
System.out.println("Student has to wait some time");
try
{
sleep(100);
} catch (InterruptedException ex) {}
}
else /* if professor (busy) and Ta1
{ /* is busy check for Ta2
Synchsema.student++; /* if Ta2 is free then Student allotted to Ta2.
System.out.println("student " + Thread.currentThread().getName() + "alloted to Ta2");
}
} // if ta1
else /* if professor (busy) and Ta1
{ /* is free then Student allotted to Ta1.
Synchsema.student++;
System.out.println("student " + Thread.currentThread().getName() + "alloted to Ta1");
}
}
if (Synchsema.student >= 15) /* checking for 15 students
{ /* if students are over
Synchsema.pprof = false; /* threads will be put as false.
Synchsema.ta1 = false; /* and not used
Synchsema.ta2 = false;
}
}
public static void main(String args[]) /* main function for process creation
{ /* and thread creation
Synchsema ss = new Synchsema();
// ss.call();
Processprof pprof = new Processprof();
Processta1 ta1 = new Processta1();
Processta2 ta2 = new Processta2();
Calendar calendar = new GregorianCalendar();
int hour = calendar.get(Calendar.HOUR);
for(int i=1; i<=5; i++)
{
new Thread(pprof, "P: "+i).start();
new Thread(ta1, "t1: "+i).start();
new Thread(ta2, "t2: "+i).start();
}
if(hour==(hour+4)) /* checking for within working hours
{
pprof.Blocked();
ta1.Blocked();
ta2.Blocked();
}
}
}
class Processprof extends Thread /* Class for checking the condition whether the Professor
{ /* or TA1 or TA2 available
public void run()
{
Synchsema.call();
}
}
class Processta1 extends Thread /* Class for checking the condition whether the Professor
{ /* or TA1 or TA2 available
public void run()
{
Synchsema.call();
}
}
class Processta2 extends Thread /* Class for checking the condition whether the Professor
{ /* or TA1 or TA2 available
public void run()
{
Synchsema.call();
}
}