This topic is a refinement of : [STACK-REF] In Java, is it required to synchronize write access to an array if each thread writes to a separate cell space?
Context : We need to huge arrays of row type, to make statistical computation. [STACK-REF] let us discover that array content can be processed simultaneously by N (worker) threads.
Problem : A main thread T0 launches N workers. When all workers have finished, what T0 'sees' in array ? Is its sontent synchronized with main memory ?
(simplistic) Test case :
- Thread T0 creates a small array of bytes : 8 items.
- It starts a new new thread T1 which writes 8 other distinct values.
- T0 wait a long time, so that T1 ends before wakeup.
- Array content is displayed (by T0)
Result : T0 views it as T1 built it. Is it quite normal or accidental ?
public class TestCase extends Thread {
public static void main(String[] args) throws InterruptedException {
//Current thread (main) stands for 'T0' in topic description.
// byte : to get a very small array.
byte[] counts = { (byte) 128, (byte) 129, (byte) 130,
(byte) 131, (byte) 132, (byte) 133,
(byte) 134, (byte) 135 };
StringBuilder sb = new StringBuilder();
for ( int i = 0; i < counts.length; i++)
sb.append(counts[i]+" ");
// all values are displays as negative numbers
System.out.println("'counts' initial content = " + sb);
Thread T1 = new TestCase(counts);
T1.start();
// 'join' can't be suspected to do refresh 'counts' array.
// T1.join();
Thread.sleep(1000);
//Avoid to display each item, to avoid any unexpected
// sync, as explained in :
// see : https://stackoverflow.com/questions/21583448/what-can-force-a-non-volatile-variable-to-be-refreshed
// for ( int i = 0; i < counts.length; i++)
// System.out.println(counts[i]+" ");
sb = new StringBuilder();
for ( int i = 0; i < counts.length; i++)
sb.append(counts[i]+" ");
// all values are displayed as written by thread T1
//How 'counts' copy in L1 cache has been updated from main memory ?
System.out.println("'counts' post content = " + sb);
}
Array size being small, we imagine that each thread owns a full copy in its L1/2/... cache ( >=32Ko). When T1 ends, array is fully updated in main memory.
Question : When T0 wakeup, how it gets an 'updated' view of array, without any special instruction ?
We built more complicated tests, involving a huge array of int, and many threads under conditions as stated by [STACK-REF]. Every time, thread T0 (i. e. 'main' one), got an fully consistent view of array.
Yes I know that
Thread Caching and Java Memory model
claims : "Each Thread does not have a local copy of memory..." but answers doesn't explain clearly our problem.
@Basilevs
I expect Thread.join() to perform synchronization. Why do you reject it?
When writing initial version of test-case, I used Thread.join() statement. I got same result.
Like you, I imagined that join() request for synch. Si to test this hypothesis, I replaced join() by sleep().
...I'd recommend not to sleep while waiting ..., thread rescheduling is likely to synchronize thread's context of wake-up.
I agree fully with you. Some time after my question beeing posted, I did new test in accordance with your proposal : sleep() statement was replaced by a loop :
while (System.currentTimeMillis() - t0 < 2000) ;
Once more, I didn't see any inconsistency.
@Andrey Cheboksarov
( Oops ! I omitted to describe my PC : Win7 64bits, jdk8, proc Intel Xeon E5630)
... if you do some computation on this array and then stop in a background thread the main thread will almost always see updated values
I test it, keeping T1 in activity by a no-op loop. : You are right.
... This will print something like -11 100 100 100 ...
Right.
Q 1 : Is your answer valid so, for other processors : Power PC by example ?
Q 2 : So your answer confirm that result of my test-cas is quite Normal ?