Win a copy of The Java Performance Companion this week in the Performance forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Threads/Looping: How Can This Be?

 
Jim Shaw
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm working my way through Head First Java (2nd ed.), and got a strange result when executing the following (Ch. 15 "Code Magnets" exercise):



I executed TestThreads four times, with the following output:
one 98099
two 98099

one 97099
two 97099

one 98099
two 98099

one 98099
two 98099

The supposed correct output is:
one 98098
two 98099

I never got this result, and don't think it's particularly likely that I will on my average attempt, although it seems possible.

What bothers me is where I got:
one 97099
two 97099

It seems to me that, given I am only adding (never subtracting) to the common counter and am looping through ThreadOne 98 times before I print the result, I should NEVER get a result less than 98000 for a.getCount() in ThreadOne.

Right? Can somebody tell me what happened here?

Much obliged,

Jim Shaw
[ May 12, 2008: Message edited by: fred rosenberger ]
 
Jim Shaw
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oops, noticed that my leading spaces were removed. Kind of makes it hard to read the code. Don't know how to prevent that. Sorry!
 
Campbell Ritchie
Sheriff
Pie
Posts: 49382
62
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Use the CODE button below the message window.
You can replace the leading spaces by clicking the pencil and paper icon, then highlight the text you wish to reformat, then the CODE button. That will insert CODE tags round the whole block of code.
 
Rodrigo Tomita
Ranch Hand
Posts: 70
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jim,

Looking at your code, I think there is no guarantee that it will give you always the same result (so I don't think there is a correct answer - probably the book would tell you that better than I can ).

Anyway, when you have several threads running on the same data, you may have the situation where one thread reads a variable and another thread changes it. Then the first one updates the variable based on the value it read (which is no longer up to date).

Hope this helps.

Rodrigo
[ May 12, 2008: Message edited by: Rodrigo Tomita ]
 
fred rosenberger
lowercase baba
Bartender
Posts: 12145
30
Chrome Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Jim Shaw:
Oops, noticed that my leading spaces were removed. Kind of makes it hard to read the code. Don't know how to prevent that. Sorry!


I put the code tags in for you.
 
Rob Spoor
Sheriff
Pie
Posts: 20546
57
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I tried this as well, and even got 94098 and 94097.

I think the reason is because numeric additions are not atomic. In fact, any addition can be viewed as the following:

// 3
Now if the other thread takes the value of counter at point 2, the addition in this thread will be nullified.

I have made the updateCounter method synchronized and I got expected results several times in a row.
 
Jim Shaw
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ahh, I see Rodrigo's point...

Sometimes I'm getting a defacto subtraction due to timing issues:
ThreadTwo retrieves count and it's, say, 4372.
ThreadOne updates count to 4472.
ThreadTwo updates count to 4373, and we've lost 100.

That's ugly!

Thanks Rodrigo, and thanks to all for your helpful posts!
 
Jim Shaw
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Rob,

Yes, the answer would be to make it atomic.

Regards,

Jim Shaw
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic