I read that:
Object sync = new Object();
/* inter to monitor */
try {
sync.wait();
} catch (InterruptedException ex) {
} finally {
}
/* our code*/
/* exit from monotir */
sync.notify();
is like
synchronize (sync) {
/* our code*/
}
Does it true?
I try this in my code and it doesn’t work.
private Object data;
private Object sync = new Object();
public static void main(String[] args) {
SimpleProducerConsumer pc = new SimpleProducerConsumer();
new Thread(pc.new Producer()).start();
new Thread(pc.new Consumer()).start();
}
public Object pop() {
try {
sync.wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("Before");
Object d = data;
data = null;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("pop");
System.out.println("After");
sync.notify();
return d;
}
public void push(Object d) {
try {
sync.wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
data = d;
System.out.println("push");
sync.notify();
}
class Producer implements Runnable {
@Override
public void run() {
while (true) {
push(new Object());
}
}
}
class Consumer implements Runnable {
@Override
public void run() {
while (true) {
pop();
}
}
}
What is wrong with my code?
No,
sync.wait()andsync.notify()are far from synonyms tosychronize (sync) { ...and... }.In fact, in order to call
waityou have to be in asynchronizedblock.I’ll explain the concepts of
synchronize,waitandnotifyand the difference will be clear.When a thread enters a
synchronized (sync) { ... }block it grabs the lock of thesyncmonitor (meaning that the lock is taken and that no other thread can enter the block at that point).When a thread calls
sync.wait()it temporarily releases the lock ofsync. (It’s waiting for something to happen. Something that requires the lock to be able to happen.)A thread calls
sync.notify()to notify other threads that something has happened, at which point they resume execution.I assume you for instance want to make sure that if two threads try to pop something they should avoid doing the following:
To avoid this you need to make sure that
d = dataanddata = nullhappens atomically.This can be achieved by doing
(Now the first and second statement in Thread 1 above can’t be split up.)
Furthermore you seem to want
popto be blocking, i.e. ifd == nullit should wait for some other thread topushsomething.This can be achieved by doing
and do
sync.notify()inpush(again within asynchronizedblock covering everything that needs to be done atomically in the push method).Related question / further reading:
Why must wait() always be in synchronized block
My answer over here gives an example of what could happens in a producer / consumer situation if
waitandnotifywhere allowed to be called outside a synchronized block.