Granny's Programming Pearls
"inside of every large program is a small program struggling to get out"
JavaRanch.com/granny.jsp
The moose likes Threads and Synchronization and the fly likes Thread actions on variables and memory Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "Thread actions on variables and memory" Watch "Thread actions on variables and memory" New topic
Author

Thread actions on variables and memory

Jose Botella
Ranch Hand

Joined: Jul 03, 2001
Posts: 2120

This question was asked in SCJP forum. I agree that none option can be discarded.
I want to apply the chapter 17 of JLS in a similar fashion as
this drawing
for the explanation.
These are the actions performed by one of the threads over the shared variable x, main memory
and the working copy wc:
lock
|
read x (0) //because of lock action
|
load (wc = 0)
|
use (operand stack = 0)
|
increment op. st.
|
assing (wc = 1)
|
[store] (optional)
|
[write] (x = 1)
| //point A
[read x is 1] (optional)
|
[load] (wc = 1)
|
use (println(wc))
|
unlock (store and write x)
I think some actions are optional due to

Provided that all the constraints above and below are obeyed, a load or store action may be
issued at any time by any thread on any variable, at the whim of the implementation.
from
JLS 17.3 Rules about variables
If the previous sequence is correct, to deduce the ouput I have placed two of such
sequences in parallel, and shift one up and down respect the other.
Output 12 : the thread that prints 2 reads x after the other has written to it.
Output 11: the thread that prints the second 1 reads x before the other writes to it
Output 22: the thread that prints the first 2 reaches point A and writes x = 1. Then the other proceeds until the same point and writes x = 2, this thread will print 2. The first one will read x and print 2 (*)
Ouput 21: the thread that prints 2 reaches point A and writes x = 1. Then
the other proceeds until the same point and writes x = 2. The former thread reads x and will print 2. The second thread however does not read x, thus its wc is still 1 and this is what it prints (*)
(*) though these explanations suggest intensive thread swapping, I think it is more likely that the behaviour can be attributed to the fact that reads and writes of the same variable on behalf of several threads are not order. It was just a simple way to explain it.
Can you spot any flaw above? TIA.


SCJP2. Please Indent your code using UBB Code
David Weitzman
Ranch Hand

Joined: Jul 27, 2001
Posts: 1365
You're thinking too hard . Synchronized blocks exists in part to solve the problem of fields having inconsistant values when viewed by different threads.
Read section 17.6, "Rules about the Interaction of Locks and Variables". When you enter a synchronized block, you know that any cached variable values will be updated before you retrieve them, and any writes during the block will be actually applied at the end of the block.
[ September 14, 2003: Message edited by: David Weitzman ]
Jose Botella
Ranch Hand

Joined: Jul 03, 2001
Posts: 2120
Thanks David.
But I have also included the lock and unlock action on the sequence, and still the two threads can be executed concurrently because the locks are different Test objects.
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Indeed, all four options are possible here, because even though the method is synchronized, it's an instance method updating a class field. Two different Test instances can perform their updates concurrently, and since they share the static x field, they can get all the wierd results listed. E.g.
thread 1: enter sync block, get value of x = 0.
thread 2: enter sync block, get value of x = 0;
thread 1: execute x++, update local copy of x from 0 to 1.
thread 2: execute x++, update local copy of x from to 1.
thread 1: print x as 1.
thread 2: print x as 2.
thread 1: exit sync block, update x on heap with local value, 1.
thread 2: exit sync block, update x on heap with local value, 1.
Lots of other sequences are possible - suffice to say, all the possibilities listed in the original proglem are valid. Note that 22 is possible because although an update of main memory is not guaranteed until the sync block exits, it may happen sooner.
If x were not static, then the only option would be 11. (Since both threads have different copis of x. Or if m() were static, then possibilities would be 12, or 21, nothing else.


"I'm not back." - Bill Harding, Twister
David Weitzman
Ranch Hand

Joined: Jul 27, 2001
Posts: 1365
Oops. Hadn't noticed it was two different instances
Jose Botella
Ranch Hand

Joined: Jul 03, 2001
Posts: 2120
Thanks Jim.
I think that if m() were static the output would be 12. Given that the threads are properly synchronized the second thread to execute m() will always read 1.
 
Don't get me started about those stupid light bulbs.
 
subject: Thread actions on variables and memory