• 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:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Paul Clapham
  • Ron McLeod
Sheriffs:
  • Jeanne Boyarsky
  • Liutauras Vilda
Saloon Keepers:
  • Tim Holloway
  • Carey Brown
  • Roland Mueller
  • Piet Souris
Bartenders:

questions of threads and synchronizing

 
Ranch Hand
Posts: 95
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have a few questions on synchronizing...I think once I get these questions resolved, I will have a good handle on ch.9 in the sierra.bates book!!


I see a code example in the book as follows:




1. First, isn't it correct that the above function is the same as:




2. Why is a run() function specified as synchronized (since the run() function is called by the JVM) ? Is that ONLY so that it can call the notify() method?

 
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

Rachel Glenn wrote:...First, isn't it correct that the above function is the same as...


Correct.

Rachel Glenn wrote:Why is a run() function specified as synchronized (since the run() function is called by the JVM) ? Is that ONLY so that it can call the notify() method?


Frankly, I'm not sure why run method is synchronized. It is something like creating a thread class (either by extending Thread or implementing Runnable) and killing its multi-threading functionality (because when run method is synchronized, only one thread can execute run method at a time - which is exactly like invoking run method manually, without creating threads).

Secondly, in general, synchronization is used to prevent multiple threads entering into a common area. You can call notify inside a synchronized block, but its not the only purpose of synchronized block. Besides, in your code, nobody is invoking wait method, so notify method is of no use.

I hope this answers your question.
 
Rachel Glenn
Ranch Hand
Posts: 95
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well the reason I thought the run() methed had a synchronized block in it was so that you would call notify(). But wouldn't it be sufficient then to rewrite the entire method as follows:


It should never block or have to wait at the synchronized(this) line of code, so it serves the purpose of being able to call notify...
 
Sheriff
Posts: 9709
43
Android Google Web Toolkit Hibernate IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well the example you have provided doesn't use synchronization for a normal use case. As Anayonkar said run method is generally not synchronized. You are right to call notify method you need a synchronized block. I personally would suggest you don't confuse yourself too much with just this example. See other examples of synchronization (and wait-notify although if I remember correctly wait-notify is no longer on the SCJP exam)...
 
Rachel Glenn
Ranch Hand
Posts: 95
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Ankit Garg wrote:Well the example you have provided doesn't use synchronization for a normal use case. As Anayonkar said run method is generally not synchronized. You are right to call notify method you need a synchronized block. I personally would suggest you don't confuse yourself too much with just this example. See other examples of synchronization (and wait-notify although if I remember correctly wait-notify is no longer on the SCJP exam)...



The other part to this example is the following code:



Isn't it correct that when the main function reaches the synchronized(b) line of code, that the ONLY way it will be placed into a waiting state is if some other object has a lock on the object b? Also, is this correct..?

1. If the main function reaches the line of code and no other object has a lock on b, then the code will get a lock on b, and proceed to the statement, and then hit the , where it will wait until a notify is received.

2. If the main function reaches the line of code and the lock object b is taken, then the code will go into a wait state (waiting for the lock on b to be available). Only after the lock becomes available does the code then execute the println code
 
Anayonkar Shivalkar
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
Now we are talking

Yes, your understanding is almost correct (and now the synchronized run method makes some sense).

Just few modifications:
1) In your very first code, when the whole run method was synchronized, the outside world would get thread-safe value of 'total'. That is - either value before thread starts, or the value after thread has completed the operation. However, in your second version of code (where synchronized block in inside for loop), 'total' is not thread safe. It is possible that other thread may access 'total' during the ThreadB operation.

2) Due to thread-unsafety mentioned above, in second version of code, 'Hello there' may get printed in between for loop of ThreaB. If complete run method is synchronized, then this won't happen - 'Hello there' will be either printer before the loop, or after complete execution of the loop.

3) You've mentioned the synchronization order properly, but please note that this is not the only possible way. E.g. it is very much possible that ThreadB will enter synchronized block first, will complete the execution, invoke notify, and exit. After this, ThreadA (i.e. main method) enters in synchronized block, prints 'Hello there' and waits.
The problem here is, now, there's nobody to notify ThreaA, and it will keep on waiting infinitely.

This is the exact reason why it is a good practice to invoke wait method in a loop which always checks a condition (deciding whether the thread should start waiting or not).

I hope this helps.
 
Rachel Glenn
Ranch Hand
Posts: 95
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Anayonkar Shivalkar wrote:Now we are talking

Yes, your understanding is almost correct (and now the synchronized run method makes some sense).

Just few modifications:
1) In your very first code, when the whole run method was synchronized, the outside world would get thread-safe value of 'total'. That is - either value before thread starts, or the value after thread has completed the operation. However, in your second version of code (where synchronized block in inside for loop), 'total' is not thread safe. It is possible that other thread may access 'total' during the ThreadB operation.

2) Due to thread-unsafety mentioned above, in second version of code, 'Hello there' may get printed in between for loop of ThreaB. If complete run method is synchronized, then this won't happen - 'Hello there' will be either printer before the loop, or after complete execution of the loop.

3) You've mentioned the synchronization order properly, but please note that this is not the only possible way. E.g. it is very much possible that ThreadB will enter synchronized block first, will complete the execution, invoke notify, and exit. After this, ThreadA (i.e. main method) enters in synchronized block, prints 'Hello there' and waits.
The problem here is, now, there's nobody to notify ThreaA, and it will keep on waiting infinitely.

This is the exact reason why it is a good practice to invoke wait method in a loop which always checks a condition (deciding whether the thread should start waiting or not).

I hope this helps.




Yes it helps thank you! Yes I realized in the second version that the entire run function is not synchronized, but I coded it that way just to demonstrate that the run function would have to resort to that in order to call notify.

BUT, just to confirm, when the statement synchronized(b) is reached, the thread executing that statement will check, right then and there, whether it has the lock on b, and if it does not, then it waits for the lock. correct?
 
Anayonkar Shivalkar
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

Rachel Glenn wrote:BUT, just to confirm, when the statement synchronized(b) is reached, the thread executing that statement will check, right then and there, whether it has the lock on b, and if it does not, then it waits for the lock. correct?


Logically, yes.

What happens actually is: when a synchronized statement is reached, the thread(say T1) simply tries to acquire the lock on that object.
If the lock is acquired by other thread(say T2), then T1 cannot proceed. Once T2 releases the lock, then T1 will acquire it and proceed.

T1 will not acquire the lock unless T2 releases it.

This is the exact reason while using cocurrent APIs (e.g. ReentrantLock etc.) unlock method should be invoked in finally block (otherwise, if an exception occurs before unlock, the lock will never be available to another thread).
 
Rachel Glenn
Ranch Hand
Posts: 95
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Anayonkar Shivalkar wrote:

Rachel Glenn wrote:BUT, just to confirm, when the statement synchronized(b) is reached, the thread executing that statement will check, right then and there, whether it has the lock on b, and if it does not, then it waits for the lock. correct?


Logically, yes.

What happens actually is: when a synchronized statement is reached, the thread(say T1) simply tries to acquire the lock on that object.
If the lock is acquired by other thread(say T2), then T1 cannot proceed. Once T2 releases the lock, then T1 will acquire it and proceed.

T1 will not acquire the lock unless T2 releases it.

This is the exact reason while using cocurrent APIs (e.g. ReentrantLock etc.) unlock method should be invoked in finally block (otherwise, if an exception occurs before unlock, the lock will never be available to another thread).



Thank you! that makes perfect sense!
reply
    Bookmark Topic Watch Topic
  • New Topic