wood burning stoves 2.0*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Problem with threads (concurrency) Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Problem with threads (concurrency)" Watch "Problem with threads (concurrency)" New topic
Author

Problem with threads (concurrency)

Igor Bo
Greenhorn

Joined: Jul 15, 2010
Posts: 12
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.
Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9291
    
  17

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...


SCJP 6 | SCWCD 5 | Javaranch SCJP FAQ | SCWCD Links
Trivikram Kamat
Ranch Hand

Joined: Sep 26, 2010
Posts: 155
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.


OCPJP6
Igor Bo
Greenhorn

Joined: Jul 15, 2010
Posts: 12
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

Joined: Jul 15, 2010
Posts: 12
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!!!
Lester Burnham
Rancher

Joined: Oct 14, 2008
Posts: 1337
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

Joined: Jul 15, 2010
Posts: 12
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

Joined: Oct 14, 2008
Posts: 1337
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.
Khoder Wassouf
Ranch Hand

Joined: Dec 02, 2010
Posts: 32
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

Joined: Jul 15, 2010
Posts: 12
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

Joined: Jul 15, 2010
Posts: 12
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

Joined: Jul 15, 2010
Posts: 12
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.
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18532
    
  40

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
Sheriff

Joined: Sep 28, 2004
Posts: 18532
    
  40


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

Joined: Jul 15, 2010
Posts: 12
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!
 
jQuery in Action, 2nd edition
 
subject: Problem with threads (concurrency)
 
Similar Threads
join() vs. synchronized
queries on threads
Regarding Syncronization
Synchronised Vs. Non synchronised Thread
Synchronized method won't let other thread go, why?