Reputation: 15
I have a doubt that is somewhat confusing me in java thread synchronization, if I have a shared memory zone, what is the difference between using wait/notify/notifyAll in the synchronized methods and declaring an Object (Object myObj) and using myObj.wait, as far as I understand both somewhat achieve the same.
In other words: This
public class ThreadSignal{
protected boolean isDataAvailable = false;
public void synchronized waitUntilComplete(){
if(isDataAvailable == false){
wait();
}
}
public void synchronized complete(){
isDataAvailable = true;
notify();
}
}
vs This
private Object notEmpty = new Object();
private Object notFull = new Object();
public synchronized E take() {
//some code
notEmpty.wait()
//some code
notFull.notifyAll();
}
Is the difference in that the first one locks the whole object thus no other thread gets access to that shared region and in the second one we get more flexibility in what we want to lock down?
Second question since putting this in a comment is hard (editing main post for it):
I have a problem Im trying to resolve and figuring the best way to architect the class, the problem is as follows there's an airport with a queue (shared region) and three threads (pilot,hostess and passenger), the hostess is basically the check in from the airport.
The passenger first enters queue and waits for the operation checkDocuments from the hostess (so it gets in a blocking/waiting state) then it presents the plane ticket and waits for the operation waitForNextPassenger of the hostess to procceed inside the plane. The hostess on the other hand wakes up by the operation waitInQueue of the passenger (when it first enters the queue), checks the passenger and then gets in another wait state that waits for the passengers documents and then checks in the passenger.
Given this I have defined these blocking variables: waitInQueue checkDocuments showingDocuments waitForNextPassenger
Given what you said in the comment, I suppose a good approach would be to make each of these an object and for example in the thread passenger lifecycle it would call the method WaitInQueue that would wait for the object checkDocuments (checkDocuments.wait) and the hostess would for example checkDocuments.notify
Is this a correct approach?
Upvotes: 0
Views: 89
Reputation: 51497
A synchronized method:
public void synchronized f() {...}
is identical to:
public void f() {
synchronized(this) {
...
}
}
which is different from:
private Object obj=new Object()
public void f() {
synchronized(obj) {
...
}
}
The synchronized method uses this
, which means any other synchronized method working on the same object will wait until the current synchronized method returns. When you use a separate object with a synchronized block, the synchronized block will wait until the current synchronized block using the same object exits. So with the second approach, you can do:
public void f() {
synchronized(obj) {
...
}
// Do stuff
synchronized(obj) {
...
}
}
That is, you can control the mutual exclusion in a more granular way.
The second approach also allows you to lock multiple objects.
You have to be careful about wait
/notify
when you're using the second approach. You can call obj.wait()
if you are holding the lock for obj
, meaning you are in a synchronized block synchronized(obj)
. When wait
is called, the synchronized block will relinquish the lock on that object. Then, another thread can use obj.notify()
to send notifications to waiting threads.
Upvotes: 1