Reputation: 1025
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?
Upvotes: 1
Views: 171
Reputation: 421040
No, sync.wait()
and sync.notify()
are far from synonyms to sychronize (sync) { ...
and ... }
.
In fact, in order to call wait
you have to be in a synchronized
block.
I'll explain the concepts of synchronize
, wait
and notify
and the difference will be clear.
When a thread enters a synchronized (sync) { ... }
block it grabs the lock of the sync
monitor (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 of sync
. (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.
What is wrong with my code?
I assume you for instance want to make sure that if two threads try to pop something they should avoid doing the following:
Thread 1 Thread 2
--------------------------------------
Object d = data;
Object d = data;
data = null;
data = null;
return d;
return d;
To avoid this you need to make sure that d = data
and data = null
happens atomically.
This can be achieved by doing
Object d;
synchronized (sync) {
d = data;
data = null;
}
(Now the first and second statement in Thread 1 above can't be split up.)
Furthermore you seem to want pop
to be blocking, i.e. if d == null
it should wait for some other thread to push
something.
This can be achieved by doing
synchronized (sync) {
while (d == null)
sync.wait();
}
and do sync.notify()
in push
(again within a synchronized
block 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 wait
and notify
where allowed to be called outside a synchronized block.
Upvotes: 3
Reputation: 79838
No, they're completely different. You call wait()
from inside a synchronized
block, if you want to suspend execution until some condition is met. You use notify()
or notifyAll()
on the same object, (again in a synchronized
block) once that condition is met.
So in this circumstance, two threads can actually be in synchronized
blocks on the same object at the same time; this is allowed when one of them has done a wait()
. The first thread starts up again once the second thread exits the synchronized
block in which it called notify()
.
Upvotes: 1
Reputation: 1865
You have both your push()
and pop()
methods waiting on the same lock object for a notify()
, but there's no one that calls notify()
or notifyAll()
on that object, so they're waiting indefinitely.
What happens here is:
sync.wait()
call inside push()
for someone to call sync.notify()
sync.wait()
call inside pop()
for someone to call sync.notify()
Upvotes: 1