• 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
  • Jeanne Boyarsky
  • Ron McLeod
Sheriffs:
  • Paul Clapham
  • Liutauras Vilda
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Roland Mueller
Bartenders:

Help needed with synchronization.

 
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi, I am trying the following code for synchronization:




The output I get is something like this:
Fred making withdrawal. Balance is: 50.0
Fred withdrawal complete. Current balance: 40.0
Fred making withdrawal. Balance is: 40.0
Fred withdrawal complete. Current balance: 30.0
Fred making withdrawal. Balance is: 30.0
Fred withdrawal complete. Current balance: 20.0
Fred making withdrawal. Balance is: 20.0
Fred withdrawal complete. Current balance: 10.0
Fred making withdrawal. Balance is: 10.0
Fred withdrawal complete. Current balance: 0.0
Lucy- Insufficient balance: 0.0
Lucy- Insufficient balance: 0.0
Lucy- Insufficient balance: 0.0
Lucy- Insufficient balance: 0.0
Lucy- Insufficient balance: 0.0

My question is this:
I have created 2 threads, one for Lucy and one for Fred. I also have a sleep(500) in the synchronized code. How come the threads are not alternating..like follows:

Fred making withdrawal. Balance is: 50.0
Fred withdrawal complete. Current balance: 40.0
Lucy making withdrawal. Balance is: 40.0
Lucy withdrawal complete. Current balance: 30.0

Why aren't the threads being interrupted as they should be in any JVM? What mistake does the code have, if any to accomplish this. Any help?!
 
Ranch Hand
Posts: 679
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

C Jay wrote:I also have a sleep(500) in the synchronized code.


That just means the thread will do nothing for 500ms. It still holds the lock on the synchronized method, so the other thread can't enter that method. Put the sleep in the run method after the call to makeWithdrawal.
 
C Jay
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,
I understand what the sleep(500) does here. The whole point of having this sleep(500) is to allow another thread check on the balance before withdrawal. Let me make this clear. This example is from K&B certification book, with minor modifications. There are 2 threads, both running on the same account. Say Fred enters it first. Fred checks account balance. Balance is more than 10(withdrawal amount). Now before doing a withdrawal, his thread sleeps for 500 milliseconds, so another thread (here Lucy is waiting in the next thread on the same account) can do the same account balance. She should be able to see the balance. Now Lucy's thread sleeps for 500 milliseconds, while runnable Fred thread resumes and continues to make withdrawal... and so on. So the 2 threads have to take turns because:
1. There is a sleep() in between check account balance and withdraw
2. Both the threads use the same account.

So my question still stands. Why isn't my output showing Fred and Lucy alternate? Why is one thread completing fully (here Fred is able to do all 5 withdrawal's before Lucy even gets a chance..) without giving the other a chance.. Anybody? Please help.
 
author
Posts: 23958
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

C Jay wrote: Hi,
I understand what the sleep(500) does here. The whole point of having this sleep(500) is to allow another thread check on the balance before withdrawal. Let me make this clear. This example is from K&B certification book, with minor modifications. There are 2 threads, both running on the same account. Say Fred enters it first. Fred checks account balance. Balance is more than 10(withdrawal amount). Now before doing a withdrawal, his thread sleeps for 500 milliseconds, so another thread (here Lucy is waiting in the next thread on the same account) can do the same account balance. She should be able to see the balance. Now Lucy's thread sleeps for 500 milliseconds, while runnable Fred thread resumes and continues to make withdrawal... and so on. So the 2 threads have to take turns because:
1. There is a sleep() in between check account balance and withdraw
2. Both the threads use the same account.



As Stuart already mentioned, no, Lucy will be waiting outside of the makeWithdrawal() method waiting for the lock to be released. She will not be able to do anything, until Fred releases the lock.

Henry
 
C Jay
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Stuart and Henry:
Thanks for your replies and reading them is convincing.. that Fred will complete 5 withdrawals before Lucy enters since the synchronized is in the makeWithdrawal() method. But K&B book has the following result for almost similar code:

Fred making withdrawal. Balance is: 50.0
Fred withdrawal complete. Current balance: 40.0
Lucy making withdrawal. Balance is: 40.0
Lucy withdrawal complete. Current balance: 30.0

And this result is what I am not getting. Does it mean that K&B code is incorrect? I tried using
a. synchronized(this) or
b. synchronized(acct)

instead of synchronized on the method withdrawal (as suggested by other websites for the same code) but still I am not getting the result that the book has printed. I am hoping that some of our ranchers might have tried the same from K&B book for the example above. Did anybody get the same result as what the book says it should? Any light on this is greatly appreciated.. I have been breaking my head with this for the past 48 hours..
 
Henry Wong
author
Posts: 23958
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

C Jay wrote: ... But K&B book has the following result for almost similar code:

Fred making withdrawal. Balance is: 50.0
Fred withdrawal complete. Current balance: 40.0
Lucy making withdrawal. Balance is: 40.0
Lucy withdrawal complete. Current balance: 30.0

And this result is what I am not getting. Does it mean that K&B code is incorrect? I tried using
a. synchronized(this) or
b. synchronized(acct)

instead of synchronized on the method withdrawal (as suggested by other websites for the same code) but still I am not getting the result that the book has printed. I am hoping that some of our ranchers might have tried the same from K&B book for the example above. Did anybody get the same result as what the book says it should?



If you take a closer look, you will see that the lock does get released, so Fred and Lucy can switch -- but it will be really really tight. Fred releases the lock, and then immediately tries to reacquires it. The OS has to context switch during this really small interval.

If you are looking to match the book exactly, you may have to consider changing the operating system, or even the machine that the operating system is running on... as it is the underlying OS that does the scheduling, and the OS may be affected by the hardware.

Henry
 
C Jay
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Henry,
I tried changing to sleep(1*60*1000); still for 1 minute Fred only seems to hold the code, and nothing else changes. He withdraws 5 times ( checks balance, 1 minute break window, withdraws amount) before Lucy gets her first turn. I understand that underlying OS/JVM does the scheduling..but 1 minute is long enough for Lucy's thread to get a chance, right? That too..this happens for 5 times..consistently...too strange..
I will see if I can run the code in a different OS, but in the meantime I thought I will update you with what I've tried after your reply.
 
Henry Wong
author
Posts: 23958
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

C Jay wrote:Henry,
I tried changing to sleep(1*60*1000); still for 1 minute Fred only seems to hold the code, and nothing else changes. He withdraws 5 times ( checks balance, 1 minute break window, withdraws amount) before Lucy gets her first turn. I understand that underlying OS/JVM does the scheduling..but 1 minute is long enough for Lucy's thread to get a chance, right? That too..this happens for 5 times..consistently...too strange..
I will see if I can run the code in a different OS, but in the meantime I thought I will update you with what I've tried after your reply.




As already mentioned by Stuart, and reaffirmed by me (in my first response), In your program, the sleep() method is called *with* the lock. Increasing the size of the sleep() will just make the program run longer, Lucy can't run while Fred is holding the lock, regardless of how long you sleep.

If you want the context switch to have a better chance of happening, you will need to sleep when Fred is *not* holding the lock. Move the sleep() method call to outside of the synchronized call, and it will work.

Henry
 
C Jay
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

As already mentioned by Stuart, and reaffirmed by me (in my first response), In your program, the sleep() method is called *with* the lock. Increasing the size of the sleep() will just make the program run longer, Lucy can't run while Fred is holding the lock, regardless of how long you sleep.

If you want the context switch to have a better chance of happening, you will need to sleep when Fred is *not* holding the lock. Move the sleep() method call to outside of the synchronized call, and it will work.



Yes, Henry. Keeping synchronized in the withdrawal method and moving the sleep method outside as follows, work:




On one hand, SCJP 6: K&B code has the sleep method inside the withdrawal method between the steps of getbalance() and withdraw(amt), and the output shows that Lucy and Fred take turns. -->A
In another page, the same book states that sleep() keeps locks (as you and Stuart had confirmed earlier; Page 740; Methods and Lock status table).-->B

I believe that B is correct, but then my confusion was to the output in A. If sleep does not give the lock, how come Lucy got a chance as in output A?
I hope you understand what I am trying to say here.
 
Henry Wong
author
Posts: 23958
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

C Jay wrote:
On one hand, SCJP 6: K&B code has the sleep method inside the withdrawal method between the steps of getbalance() and withdraw(amt), and the output shows that Lucy and Fred take turns. -->A



I don't know what to tell you. With threads, you need to understand what race conditions can exist. Some race conditions has outcomes that exist only with certain operating systems. Some outcomes only exist with certain hardware. Some outcomes with only certain load conditions. And some race conditions have outcomes that is only theoretical, meaning that they may never happen.

If you need to see the different outcomes before you believe that a race condition exist, you are going to be generating a lot of code that have benign race conditions, that may break when you run in on different machines, upgrade to different hardware, or run under different loads.


C Jay wrote:
In another page, the same book states that sleep() keeps locks (as you and Stuart had confirmed earlier; Page 740; Methods and Lock status table).-->B

I believe that B is correct, but then my confusion was to the output in A. If sleep does not give the lock, how come Lucy got a chance as in output A?
I hope you understand what I am trying to say here.



What is output A? (oh, you mean the previous paragraph)

The first output has nothing to do with the sleep() call. Since the sleep() method doesn't give up the lock, Lucy doesn't get a chance to run due to the sleep() method call. It happens because there is a point, at the loop, where the lock is released.

Henry
 
Rancher
Posts: 1090
14
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

C Jay wrote:Hi Stuart and Henry:

instead of synchronized on the method withdrawal (as suggested by other websites for the same code) but still I am not getting the result that the book has printed. I am hoping that some of our ranchers might have tried the same from K&B book for the example above. Did anybody get the same result as what the book says it should? Any light on this is greatly appreciated.. I have been breaking my head with this for the past 48 hours..

....

On one hand, SCJP 6: K&B code has the sleep method inside the withdrawal method between the steps of getbalance() and withdraw(amt), and the output shows that Lucy and Fred take turns. -->A
In another page, the same book states that sleep() keeps locks (as you and Stuart had confirmed earlier; Page 740; Methods and Lock status table).-->B



Well, I have the book. And I can't see the text ( 'it should') you mention. The books says it very clearly in more than one places that with threads ( with unresolved race conditions ), very little is guaranteed.

And it has been said many times already that when access to a block is not synchronized in a way that guarantees the same behaviour in ALL the conditions, you can't predict the answer to some of the why X did not happen, why Y happened questions because of the reasons stated already. The book has shown you one of the several possible outcomes. If you run your program several times, you may get a different output. That does not mean the previous outputs were wrong.
 
C Jay
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Well, I have the book. And I can't see the text ( 'it should') you mention. The books says it very clearly in more than one places that with threads ( with unresolved race conditions ), very little is guaranteed.



The output text (if the method is synchronized) is in SCJP 6 (K&B) edition 8, page 734 for your reference.
 
Ranch Hand
Posts: 574
VI Editor Chrome Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You need to wrap your brain around synchronization, and the OS scheduler, and how they interact. You can not guarantee who will be active after the sleep, it's not quite random but random enough that if you count on a behaviour you will regret it.

You want to create a semaphore. Either Lucy or Fred gets it, not both at the same time, one always holds it. No idea how to do it in Java, I'm a *nix guy.
 
rubbery bacon. crispy tiny ad:
Smokeless wood heat with a rocket mass heater
https://woodheat.net
reply
    Bookmark Topic Watch Topic
  • New Topic