| Author |
Confused about Thread synchronization
|
Mark Lau
Ranch Hand
Joined: Dec 15, 2001
Posts: 120
|
|
I don't think that I am ever clear about Thread synchronization. A code snippet from Page 529 of Sierra and Bates: I am really confused about line 7 and 8. In line 7, the main method says that it is "Waiting for b to complete", and then in line 8, the main method says b.wait(); So, who the heck is waiting? The main or b? Line 8 seems to be saying "Let b wait" and this conflicts with what the main says in Line 7. Please shed some light on me. Thanks. Gene [ September 05, 2003: Message edited by: Gene Chao ]
|
 |
Mark Lau
Ranch Hand
Joined: Dec 15, 2001
Posts: 120
|
|
It seems that my understanding of the wait() method is contrary to what it really is. It looks like when ThreadA calls b.wait(), ThreadA is really saying, "little b, go ahead and finish your job, I will be here waiting for you. Let me know when you are done.". Is this right? [ September 05, 2003: Message edited by: Gene Chao ]
|
 |
Anupam Sinha
Ranch Hand
Joined: Apr 13, 2003
Posts: 1088
|
|
Hi Gene I am afraid not. b.wait() means the thread b is waiting. You can use the join() method in case you wish that thread threadA should wait for thread b to finish its work and then intimate thread threadA when done. wait(), notify() and notifyAll() are defined in the Object class. Join() method is defined in the Thread class.
|
 |
Mark Lau
Ranch Hand
Joined: Dec 15, 2001
Posts: 120
|
|
I am afraid not. b.wait() means the thread b is waiting.
Then would you please explain Line 7 and Line 8? Thanks.
You can use the join() method in case you wish that thread threadA should wait for thread b to finish its work and then intimate thread threadA when done.
Yes, this I understand
|
 |
Ernest Friedman-Hill
author and iconoclast
Marshal
Joined: Jul 08, 2003
Posts: 24057
|
|
Sorry, but b.wait() means that the CALLER (here, a) should wait until someone calls b.notify(). You don't show the code for b, but presumably the run() method in the ThreadB class calls notify() -- otherwise "a" would wait forever. The object you call wait() on is used as a kind of "message board;" the word people usually use is "monitor."
|
[Jess in Action][AskingGoodQuestions]
|
 |
Anupam Sinha
Ranch Hand
Joined: Apr 13, 2003
Posts: 1088
|
|
Hi Gene Can you paste the full code.
|
 |
Mark Lau
Ranch Hand
Joined: Dec 15, 2001
Posts: 120
|
|
OK, here is the full code.
Sorry, but b.wait() means that the CALLER (here, a) should wait until someone calls b.notify(). You don't show the code for b, but presumably the run() method in the ThreadB class calls notify() -- otherwise "a" would wait forever. The object you call wait() on is used as a kind of "message board;" the word people usually use is "monitor."
So ThreadA is actually saying, Little b, go ahead and finish your job, I'll be here waiting until get notified. But then, join() also works like this, the only difference is that you don't wait for any notification. So please explain any other differences between wait() and join(). Thanks a lot. Gene [ September 05, 2003: Message edited by: Gene Chao ]
|
 |
Anupam Sinha
Ranch Hand
Joined: Apr 13, 2003
Posts: 1088
|
|
Hi Ernest I don't seem to ge it. In this code threadA will wait for B, but that is I guess because b itself is waiting. I mean b is waiting because of a wait() method invocation and threadA is waiting because of b is waiting. Do I make sense? Please clarify.
|
 |
Mark Lau
Ranch Hand
Joined: Dec 15, 2001
Posts: 120
|
|
Anupam, I don't think your understanding of b.wait() is right. Earnest is right and I am probably right, too. I think I can prove this. Please read. Run the following code: And the printout will be Total is 0. This is because the main of ThreadA does not wait until ThreadB finishes. Run the following code and you'll get Total is 5050. And this is because b.join() forces the main of ThreadA to wait until b finishes its job. Run the following code, and you'll also get what you expect: Total is 5050 And this is because you put the main of ThreadA to sleep for 5 seconds,and during this time, b has finished its job. Interesting, isn't it? So, what's the difference between wait() and join()? Gene [ September 05, 2003: Message edited by: Gene Chao ]
|
 |
Anupam Sinha
Ranch Hand
Joined: Apr 13, 2003
Posts: 1088
|
|
Hi Gene Now I also think that my understanding of the wait() method may not be right. In the intial code you posted the one with b.wait(). I still don't understand which thread is going into the wait state. Try commenting out the notify staatement and see the result. I must say that it's really a nice question. Waiting for a nice answer to my queries as well.
|
 |
Ernest Friedman-Hill
author and iconoclast
Marshal
Joined: Jul 08, 2003
Posts: 24057
|
|
If you comment out the notify() in the case where A called wait(), then nothing will ever be printed, and the program won't exit; wait() will never return. If you call wait() on any object (wait() is a member of Object, not of Thread; Thread just inherits it from Object) then wait() won't return until some code, somewhere, calls notify() on that same object (there are a few details and exceptions that we won't worry about right now.) If you call join() on a Thread object (it's member of Thread) then join() won't return to the caller until that thread has terminated; so join() means what Gene was saying about "Go ahead little thread, I'll just wait here for you " I guess the reason this example is confusing is because it's mixing up several concepts at once. Frankly, I can't recall anybody ever calling wait() on a Thread object before; there's nothing wrong with it, there's just usually some other object to call it on that's better.
|
 |
Marlene Miller
Ranch Hand
Joined: Mar 05, 2003
Posts: 1391
|
|
Hi Gene, 1. Every object has a lock and a wait set. A wait set is a set of threads. 2. x.wait() means add this thread to the wait set of the object referenced by x. 3. x.notify means select and remove a thread from the wait set of the object referenced by x. synchronized(b) The main thread acquires the lock of the ThreadB object b.wait(); The main thread is added to the wait set of the ThreadB object and releases the lock of the ThreadB object. synchronized(this) thread-1 managed by the ThreadB object acquires the lock of the ThreadB object. notify() The main thread is removed from the wait set of the ThreadB object. When thread-1 releases the lock of the ThreadB object, the main thread acquires the lock and returns from wait(). [ September 05, 2003: Message edited by: Marlene Miller ]
|
 |
Marlene Miller
Ranch Hand
Joined: Mar 05, 2003
Posts: 1391
|
|
Gene, caution. If the main thread wants to wait for thread-1, it does Not have to acquire the lock of the thread-1 object and invoke wait on the thread-1 object. The main thread and thread-1 can use Any object. If you don't feel creative, just do this: Object obj = new Object(); and synchronized(obj) and obj.wait() and obj.notify() Since the virtual machine uses the Thread object to manage the thread, maybe it is Better for the main thread and thread-1 to use some other object. [ September 05, 2003: Message edited by: Marlene Miller ]
|
 |
Marlene Miller
Ranch Hand
Joined: Mar 05, 2003
Posts: 1391
|
|
Line 8 seems to be saying "Let b wait" and this conflicts with what the main says in Line 7.
No, line 8 says �Let the thread that is executing this code wait�. b refers to the object that has the wait set.
It looks like when ThreadA calls b.wait(), ThreadA is really saying, "little b, go ahead and finish your job, I will be here waiting for you. Let me know when you are done.". Is this right?
No, the main thread is saying, �virtual machine, add me to the wait set of the object that little b is pointing to. Some other thread will remove me from the wait set.� Meanwhile, the other thread is executing the run method. It's unfortunate that in this example little b is related to the other thread. [ September 05, 2003: Message edited by: Marlene Miller ]
|
 |
leonardo battagli
Ranch Hand
Joined: Aug 28, 2003
Posts: 33
|
|
In this code I don't understand why line 5. is executed before line D. In this way b is locked first then b.wait() gets called b is unlocked now then D. synchronized(this) { makes b locked again then notify() removes the lock from b again and main can finish BUT if 4. b.start(); executes D. synchronized(this) { b is first locked, then a call to notify() and then b will be unlocked while main thread will be waiting since it then executes b.wait() a no other thread calls notify on b 1. class ThreadA 2. { public static void main(String [] args) 3 { ThreadB b = new ThreadB(); 4. b.start(); 5. synchronized(b) 6. { try 7. { System.out.println("Waiting for b to complete..."); 8. b.wait(); 9. } 10. catch(InterruptedException ie) {} 11. } 12. System.out.println("Total is: " + b.total); 13. } 14.} A.class ThreadB extends Thread{ B.int total; C.public void run() { D. synchronized(this) { E. for(int i=0; i<=100; i++) F. { total += i; } G. notify(); H. } I. } L.}
|
 |
Marlene Miller
Ranch Hand
Joined: Mar 05, 2003
Posts: 1391
|
|
Hi Leonardo, You have described the sequence of events in two ways depending on which thread acquires the lock of the object first. Either way could happen when the program is run. After the main thread starts the other thread, what happens next depends on the thread scheduler. If you add Thread.yield() between 4 and 5 and test the program, you might see line D executed before line 5. 4. b.start(); Thread.yield(); // hint to scheduler to run another thread instead of this one 5. synchronized(b) [ September 07, 2003: Message edited by: Marlene Miller ]
|
 |
Deep Chand
Ranch Hand
Joined: Dec 17, 2002
Posts: 133
|
|
Correct me If I'm wrong. In the above example there is a possiblity that ThreadB can call notify before main has called a wait() on it. In that scenario, main can wait forever. Please reply soon. Thanks. Deep
|
 |
 |
|
|
subject: Confused about Thread synchronization
|
|
|