• 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
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Problem with threads (concurrency)

 
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I am preparing for SCJP and reading K&B Study Guide - the book is really great! In the chapter 9 "Synchronizing Code (Objective 4.3)" they have this example:


And I have the following output:

Can somebody explain the output, please?! I have no idea what is happening!

Running on Mac OS 10.6.5 with Java 1.0.6_22-b04-307

P.S. Did not understand the message appeared when using "AccountDanger r" instead of "AccountDanger ad" in the code(!):

We're sorry, but your post appears to contain abbreviations that we don't like people to use at the Ranch. Because JavaRanch is an international forum, many of our members are not native English speakers. For that reason, it's important that we all try to write clear, standard English, and avoid abbreviations and SMS shortcuts. See here for more of an explanation. Thanks for understanding.

If the abbreviation occurs within code, you can use code tags to post it successfully.

The specific error message is: "r" is a silly English abbreviation; use "are" instead.

 
Sheriff
Posts: 9708
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
Are you sure the code is correct?? There is only a balance of 50 in the account so withdrawal of 10 from it 10 times should not be possible.

As for the error message, generally people use sms style language like "how r u" which is hard to understand so we encourage people to use real words. In your case this system caught the r and thought it was a sms style word...
 
Ranch Hand
Posts: 155
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Ankit Garg wrote:
Are you sure the code is correct?? There is only a balance of 50 in the account so withdrawal of 10 from it 10 times should not be possible.



I agree with Ankit.
You may get withdrawal 6 or 7 times rarely if thread switching takes place at line:
balance = balance - amount;

But 10 times is highly improbable.
 
Igor Bo
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Everything is CORRECT! I've copied the code from the NetBeans. I think there is something wrong in JVM on Mac, can't explain it another way
 
Igor Bo
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Trivikram Kamat wrote:
You may get withdrawal 6 or 7 times rarely if thread switching takes place at line:
balance = balance - amount;


I think it can be only 6 withdrawals at most: after 4 withdrawals you have 10 in the balance. And then 2 threads make a 1 withdrawal each (2 withdrawal total). And the balance become -10.
There can NOT be even 7 withdrawals!!!
 
Rancher
Posts: 1337
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Igor Bo wrote:I think there is something wrong in JVM on Mac, can't explain it another way


It's extremely unlikely that such basic code would trigger a JRE bug. I just verified that it works as intended on OS X (assuming that allowing the account to go below zero is OK, but since the code does allow that I'm assuming it's fine).

Have you tried running the code outside of NetBeans, from the command line?
 
Igor Bo
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Lester Burnham wrote:
Have you tried running the code outside of NetBeans, from the command line?


Just tried. Seems that from command line it executes correctly. But can it be 7 withdrawals? Get this in terminal:

Fred is going to withdraw
Lucy is going to withdraw
Fred completes the withdrawal
Fred is going to withdraw
Lucy completes the withdrawal
Lucy is going to withdraw
Fred completes the withdrawal
Fred is going to withdraw
Lucy completes the withdrawal
Lucy is going to withdraw
Fred completes the withdrawal
Fred is going to withdraw
Lucy completes the withdrawal
Not enough in account for Lucy to withdraw 0
Not enough in account for Lucy to withdraw 0
Fred completes the withdrawal
account is overdrawn!
Not enough in account for Fred to withdraw -10
account is overdrawn!
 
Lester Burnham
Rancher
Posts: 1337
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Igor Bo wrote:But can it be 7 withdrawals?


Note that the check for overdraft happens after the withdrawal - and it causes the thread to sleep.

Also, there is no synchronization of the access to the Account object.
 
Ranch Hand
Posts: 32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you for this example!

Well this is the reason for the Output you got:

When one of the Threads goes to Sleep another Thread starts keeping the before thread in a half a second Sleep as you chose "500"
So In this case when the Thread wakes up it continues on!.............So your its like your calling the Withdraw method twice for each time so its like your saying

for(int i0;i<10;i++) instead of for(int i=0;i<5;i++)

I copied the code and written it in a different way.............Here is the Output:

...................................................................
John is going to withdraw
New Balance for: JohnIs: 40

Mary is going to withdraw
New Balance for: MaryIs: 30

John is going to withdraw
New Balance for: JohnIs: 20

Mary is going to withdraw
New Balance for: MaryIs: 10

John is going to withdraw
New Balance for: JohnIs: 0

Mary Withdraw Terminated
Mary Withdraw Terminated
Mary Withdraw Terminated
John Withdraw Terminated
John Withdraw Terminated

............................................................

Here is the Code:




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

Lester Burnham wrote:

Igor Bo wrote:But can it be 7 withdrawals?


Note that the check for overdraft happens after the withdrawal - and it causes the thread to sleep.

Also, there is no synchronization of the access to the Account object.


There is no synchronization, so each of 2 threads can ask for the balance simultaneously. To make a withdrawal they need to get at least 10 in balance. So if they ask simultaneously for the balance, get 10 and make withdrawal (2 threads * 10 = 20) the result would be -10 in balance and after that they can NOT make withdrawals anymore.
4 withdrawals to have balance of 10 + 2 withdrawals made simultaneously by threads getting balance of 10 = 6 withdrawals. How can it be 7???
Didn't get note that overdraft happens after the withdrawal. I think it's not important here because we are calculating how many times program(threads) can make withdrawals, right? Or what is the maximum number of lines "**** completes the withdrawal " in the output? **** = Fred | Lucy.
 
Igor Bo
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Igor Bo wrote:
Fred is going to withdraw
Lucy is going to withdraw
Fred completes the withdrawal
Fred is going to withdraw
Lucy completes the withdrawal
Lucy is going to withdraw
Fred completes the withdrawal
Fred is going to withdraw
Lucy completes the withdrawal
Lucy is going to withdraw
Fred completes the withdrawal
Fred is going to withdraw
Lucy completes the withdrawal
Not enough in account for Lucy to withdraw 0
Not enough in account for Lucy to withdraw 0
Fred completes the withdrawal
account is overdrawn!
Not enough in account for Fred to withdraw -10
account is overdrawn!



How I understand:

Where I am wrong?
 
Igor Bo
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Finally, I think that the reason of 7 withdrawals is that the code doesn't use synchronized methods. Without synchronization usage of shared object become unpredictable. But it's not written anywhere officially, so this conclusion is NOT advised for exam.
 
author
Posts: 23951
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Igor Bo wrote:
There is no synchronization, so each of 2 threads can ask for the balance simultaneously. To make a withdrawal they need to get at least 10 in balance. So if they ask simultaneously for the balance, get 10 and make withdrawal (2 threads * 10 = 20) the result would be -10 in balance and after that they can NOT make withdrawals anymore.
4 withdrawals to have balance of 10 + 2 withdrawals made simultaneously by threads getting balance of 10 = 6 withdrawals. How can it be 7???
Didn't get note that overdraft happens after the withdrawal. I think it's not important here because we are calculating how many times program(threads) can make withdrawals, right? Or what is the maximum number of lines "**** completes the withdrawal " in the output? **** = Fred | Lucy.



As mentioned by a few ranchers already, there is a race condition in the account withdraw method....



This one line isn't atomic. It loads the value of balance into a register, subtracts the value of amount from it, and then stores the value back into memory.

It is possible for the balance to be 50, and both Fred and Lucy withdraw 10, and the final balance to be 40.... ie. Fred loads the 50. Lucy loads the 50. Lucy subtracts 10 and puts the 40 back. Fred subtracts 10 and puts the 40 back.

Henry
 
Henry Wong
author
Posts: 23951
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Side note -- which may be interesting. The sleep(500) could be keeping money from magically appearing on the account.

Without the sleep(), even this could happen (although improbable) ... Fred loads the 50. Lucy loads the 50. Lucy subtracts 10 and puts the 40 back. Lucy loads the 40. Lucy subtracts 10 and puts the 30 back. Lucy loads the 30. Lucy subtracts 10 and puts the 20 back. Lucy loads the 20. Lucy subtracts 10 and puts the 10 back. Fred subtracts 10 and puts the 40 back.

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

Henry Wong wrote:
This one line isn't atomic. It loads the value of balance into a register, subtracts the value of amount from it, and then stores the value back into memory.


Henry, thank you for the reasonable answer!
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic