• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Tim Cooke
  • Campbell Ritchie
  • paul wheaton
  • Ron McLeod
  • Devaka Cooray
Sheriffs:
  • Jeanne Boyarsky
  • Liutauras Vilda
  • Paul Clapham
Saloon Keepers:
  • Tim Holloway
  • Carey Brown
  • Piet Souris
Bartenders:

Thread question

 
Ranch Hand
Posts: 38
Eclipse IDE Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Morning guys, I was doing another ExamLab mock and this question appeared:


It says that the answer is: Ready to print, Now printed. The explanation says that the wait() is wainting for an Trd instance, and the notifyAll() use a Thread instance. I didn't get it. Can anyone explain to me what happened?

Thanks
 
Greenhorn
Posts: 19
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Looking at the code, I would say this will throw an IllegalMonitorStateException in line 14, because the wait call is not in a synchronized block.
Also, the wait is on the Trd object whereas the notifyAll is on the Thread object. So, the notifyAll will not notify the waiting thread.
 
Bartender
Posts: 4568
9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Norbert Muench wrote:Looking at the code, I would say this will throw an IllegalMonitorStateException in line 14, because the wait call is not in a synchronized block.


It's in a synchronized method - that's the same thing as a block synchronized on that object.

But your second point is the important one. The wait() call in doMore() is on the Trd object. The notifyAll() call is on the Thread object. So there's no interaction going on. The Trd object is waiting for a notification that never comes.
 
Norbert Muench
Greenhorn
Posts: 19
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ah stupid me, I overlooked that the method itself was synchronized. Thanks for pointing that out.

But one other question:
As far as I can see, there's no guarantee that the output is "Ready to print, Now Printing, ". It could also be "Now Printing, Ready to Print, ", correct?
 
Matthew Brown
Bartender
Posts: 4568
9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That was my impression, yes (because the sleep periods are the same). In practice you might always get the same behaviour, but I don't think it's guaranteed.
 
Bartender
Posts: 1558
5
Eclipse IDE Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Norbert Muench wrote:As far as I can see, there's no guarantee that the output is "Ready to print, Now Printing, ". It could also be "Now Printing, Ready to Print, ", correct?


Correct. Theoretically, its not guaranteed in which order those Strings will be printed.
 
Ranch Hand
Posts: 136
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
So, If we want to call notifyAll() correctly, how do we call notifyAll() on Trd object?
 
Norbert Muench
Greenhorn
Posts: 19
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Same as you would call any other method.
The thread code still might get stuck in the call to wait() though, as there is no guarantee that the notifyAll() wouldn't be excuted before the wait().

 
Matheus Souza
Ranch Hand
Posts: 38
Eclipse IDE Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Norbert Muench wrote:Same as you would call any other method.
The thread code still might get stuck in the call to wait() though, as there is no guarantee that the notifyAll() wouldn't be excuted before the wait().



I got it. Thanks for the explanation =D
 
Janki Shah
Ranch Hand
Posts: 136
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you Norbert for your explanation. So, in order to work with wait(), notify(), and notifyAll()... All these three methods have to acquire a lock on an object not on threads, Right? And wait() and notify() or notifyAll() they both have to get lock on the same object to work with each other? Please correct me if I am wrong.
But this conflicts with this " the thread must own the lock on the object that wait() is being invoked on " From K & B book chapter 9 question 7.
I am very confused in this logic who should own the lock on whom??? Can you please explain this?

Norbert Muench wrote:Same as you would call any other method.
The thread code still might get stuck in the call to wait() though, as there is no guarantee that the notifyAll() wouldn't be excuted before the wait().

 
Norbert Muench
Greenhorn
Posts: 19
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Janki Shah wrote:Thank you Norbert for your explanation. So, in order to work with wait(), notify(), and notifyAll()... All these three methods have to acquire a lock on an object not on threads, Right? And wait() and notify() or notifyAll() they both have to get lock on the same object to work with each other? Please correct me if I am wrong.


That is correct.

Janki Shah wrote:But this conflicts with this " the thread must own the lock on the object that wait() is being invoked on " From K & B book chapter 9 question 7.
I am very confused in this logic who should own the lock on whom??? Can you please explain this?


Locks are on objects, but they are aquired and owned by threads. When a thread enters a synchronized block, it aquires the lock on the object the synchronized block refers to. In case of a synchronized method, this will be the object the method is called for.
Once one thread has aquired a lock on an object, no other thread can aquire a lock on the same object until the thread holding the lock releases it.
 
Janki Shah
Ranch Hand
Posts: 136
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you Norbert. It helps a lot. Thanks once again.
 
Ranch Hand
Posts: 451
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


By the way, will the following scenario be possible ?
1. t.start(), but the Trd's run method is not executed yet.
2. the main thread sleeps for 1 second
3. the main thread acquires the lock of t.
4. the main thread prints "Now printing"
5. the main thread notify all. But since the Trd's run method is not executed yet, the t thread is not waiting. There is no waiting thread to be notified at this moment.
6. Trd's run method begins to execute
7. t sleeps for 1 second as line 5 is execute.
8 t prints "Ready to print"
9. doMore is execute, but the thread t acquires the lock of its Trd instance and wait for it and release the lock. Will the thread t wait forever here and won't execute line 15?


The key points are step 5 and step 9. In step 5, there is no waiting thread and t notifies nothing.
In step 9, t is waiting for Trd and won't get notify.

I remember in KB's book, if the notify or notifyAll is called before the wait happens, there will be no thread to notify.
That is why wait and notify must be put inside some conditional statements.

Correct me if I am wrong.
 
Matheus Souza
Ranch Hand
Posts: 38
Eclipse IDE Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have another question: when I use the syncronized keyword in a static member it means that all my template (static member - variables and methods) are lockeds?
 
Norbert Muench
Greenhorn
Posts: 19
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Matheus Souza wrote:I have another question: when I use the syncronized keyword in a static member it means that all my template (static member - variables and methods) are lockeds?


No, it means that threads executing the synchronized method need to aquire a lock on the class object.
is functionally equivalent to


Helen Ma wrote:By the way, will the following scenario be possible ?


I would say yes. And the solution is described in K&B chapter 9, section "Using wait() in a Loop". Basically, before calling wait() you should check if the event you want to wait for has already happened.
 
Matheus Souza
Ranch Hand
Posts: 38
Eclipse IDE Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Norbert Muench wrote:

Matheus Souza wrote:I have another question: when I use the syncronized keyword in a static member it means that all my template (static member - variables and methods) are lockeds?


No, it means that threads executing the synchronized method need to aquire a lock on the class object.



So if I create new instace of MyClass, the synchronized methods would be locked already?
 
Sheriff
Posts: 28395
100
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Matheus Souza wrote:So if I create new instace of MyClass, the synchronized methods would be locked already?



I'm not sure quite what this means, but let me answer one of the questions it might mean:

No, creating an object will not automatically cause any code to acquire any locks it didn't already have.

If it meant something else, please correct my guess.
 
Matheus Souza
Ranch Hand
Posts: 38
Eclipse IDE Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paul Clapham wrote:

Matheus Souza wrote:So if I create new instace of MyClass, the synchronized methods would be locked already?



I'm not sure quite what this means, but let me answer one of the questions it might mean:

No, creating an object will not automatically cause any code to acquire any locks it didn't already have.

If it meant something else, please correct my guess.



This is not what meant. I want to know if I lock an method syncronized, the whole set of static members would be locked too?
 
Norbert Muench
Greenhorn
Posts: 19
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Matheus Souza wrote:This is not what meant. I want to know if I lock an method syncronized, the whole set of static members would be locked too?


I think you misunderstand how locking works. If one thread holds a lock to an object, it doesn't prevent other threads from modifying any of the objects member variables. It just prevents other threads from aquiring a lock to the same object. And threads will only aquire a lock when starting a synchronized block or synchronized method.

Take the following code as an example:


Now imagine you have two threads, thread 1 and thread 2. Thread 1 has just called MyClass.staticSyn1() and is in the middle of working through that method. So it holds a lock to the MyClass class object.
If thread 2 would start running now, it could modify the static member MyClass.si1. The fact that thread 1 holds the lock on the MyClass class object doesn't come into play here at all. Thread 2 could also call MyClass.static1(), because that class method isn't synchronized.
But what happens, if thread 2 tries to call MyClass.staticSyn1(), MyClass.staticSyn2() or syn1() on any object of type MyClass?
At the start of the synchronized block, the thread would try to aquire a lock on MyClass.class. That lock is already held by thread 1 however. So in this case thread 2 would be moved from the running state to the blocked state. Once thread 1 releases the lock on MyClass.class, thread 2 would aquire the locks and would be moved from blocked to runnable (and eventually to running).
 
Matheus Souza
Ranch Hand
Posts: 38
Eclipse IDE Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Norbert Muench wrote:

Matheus Souza wrote:This is not what meant. I want to know if I lock an method syncronized, the whole set of static members would be locked too?


I think you misunderstand how locking works. If one thread holds a lock to an object, it doesn't prevent other threads from modifying any of the objects member variables. It just prevents other threads from aquiring a lock to the same object. And threads will only aquire a lock when starting a synchronized block or synchronized method.

Take the following code as an example:


Now imagine you have two threads, thread 1 and thread 2. Thread 1 has just called MyClass.staticSyn1() and is in the middle of working through that method. So it holds a lock to the MyClass class object.
If thread 2 would start running now, it could modify the static member MyClass.si1. The fact that thread 1 holds the lock on the MyClass class object doesn't come into play here at all. Thread 2 could also call MyClass.static1(), because that class method isn't synchronized.
But what happens, if thread 2 tries to call MyClass.staticSyn1(), MyClass.staticSyn2() or syn1() on any object of type MyClass?
At the start of the synchronized block, the thread would try to aquire a lock on MyClass.class. That lock is already held by thread 1 however. So in this case thread 2 would be moved from the running state to the blocked state. Once thread 1 releases the lock on MyClass.class, thread 2 would aquire the locks and would be moved from blocked to runnable (and eventually to running).



I think that I got it. Thanks for the effort on the explanation =D
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic