| 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: 18670
|
|
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.
|
 |
 |
|
|
subject: Thread actions on variables and memory
|
|
|