As I Know only one thread can execute on a synchronize method on same block but in below producer consumer problem I am able to run both the methods.
Sample Code
import java.util.concurrent.CountDownLatch;
public class VIV {
public static void main(String[] args) throws Exception {
Number no = new Number();
//Same Object is passed
Even ev = new Even(no, 10);
Odd od = new Odd(no, 10);
Thread oddThraed = new Thread(od,"ODD");
oddThraed.start();
Thread evenThraed = new Thread(ev,"Even");
evenThraed.start();
}
}
class Number {
int no;
boolean flag=false;
public synchronized int getEvenNo() {
System.out.println("In Even Method");
// wait block so no other thread can enter on same object synchronized method
try{
wait();
}catch (Exception e) {
// TODO: handle exception
}
if(!flag) {
try {
Thread.sleep(1000);
}catch (Exception e) {
// TODO: handle exception
}
}
no=no+1;
System.out.println(Thread.currentThread().getName()+":"+no);
flag=false;
notify();
return no;
}
public synchronized int getOddNo() {
System.out.println("In ODD Method");
// wait block so no other thread can enter on same object synchronized method
try{
wait();
}catch (Exception e) {
// TODO: handle exception
}
if(flag) {
try{
wait();
}catch (Exception e) {
// TODO: handle exception
}
}
no = no+1;
System.out.println(Thread.currentThread().getName()+":"+no);
flag=true;
notify();
return no;
}
}
class Even implements Runnable {
Number num;
int noOfTime;
Even(Number no, int noOfTime) {
this.num=no;
this.noOfTime=noOfTime;
}
public void run() {
for(int i=0;i<noOfTime;i++) {
num.getEvenNo();
}
}
}
class Odd implements Runnable {
Number num;
int noOfTime;
Odd(Number no, int noOfTime) {
this.num=no;
this.noOfTime=noOfTime;
}
public void run() {
for(int i=0;i<noOfTime;i++) {
num.getOddNo();
}
}
}
OutPut :
- In ODD Method
- In Even Method
As Only one Number object is created and passed to other classes which are invoking on its two different synchronized methods. Both methods are printing the message after that waiting .
The reason that both methods get executed at the same time is that the
wait()
method releases the lock. Once yoursynchronized
method callswait()
, the lock is given back, and another thread can invoke anothersynchronized
method on the same object. Don't callwait()
inside asynchronized
method in this way!The
wait()
calls are also the reason that you're getting deadlock. This is what is happening:odd
method acquires the lock and starts executing.odd
method prints its first message.odd
method invokeswait()
, which releases the lock and waits to be notified.even
method can now acquire the lock that's been released.even
method prints its first message.even
method invokeswait()
, which releases the lock and waits to be notified.By this point, you're in the middle of both
synchronized
methods (becausewait()
releases the lock), and you're deadlocked (because both methods are waiting).Don't call
wait()
unless you're quite sure that's what you need. If yourwait()
is there just to keep it waiting to see if the synchronization can be broken, you might tryThread.sleep()
instead, which will pause without releasing any locks. Usually it's enough to declare the relevant methods or blocks assynchronized
without needing anywait
/notify
.(By the way, it's not a good idea to have a class called
Number
, because this is a standard JDK class. It's the superclass ofDouble
,Integer
, and so on.)I don't know whether you are trying to achieve this kind of thing, if you are trying to call EVEN & ODD alternatively, then I have modified your code for the same. Have a look at below code :-
Note : As suggested by @chiastic-security Number is already defined in JDK, I have renamed it to TestNumber in this code.
Output :