Win a copy of Practical SVG this week in the HTML/CSS/JavaScript forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Memory Semantics - Threads

 
Raul Gupta
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello,

Can someone please help me with following questions?
i) In case there is no synchronized block or volatile variable, when does a thread flush its state to the main memory?
Lets suppose we have an object with two integer states a and b. Thread1 is simply doing a++ and Thread2 is simply doing b++. From the perspective of visibility, can we say for certain that all the updates that Thread1 is doing would be visible immediately to Thread2? For e.g. can we say the below code would always print the most updated values of a and b for both the threads?(Note there is no race condition here)

ii) What exactly happens when a thread syncs its memory with the main memory? Does the thread updates only that state that it itself has changed and refreshes the remaining state? What if the main memory contains a state updated by some other thread. for e.g. in the above case if Thread1 was updating state b as well then how would Thread1 update state b to the main memory. Lets say Thread2 updated main memory with b = 5. But Thread1 which had some stale value of b updated b from 3 to 4 and now is trying to update the main memory. So would Thread1 update the main memory with b = 4?
iii) How does synchronization affect all this?

Hope I am clear.

Thanks,
Rahul
 
Stephan van Hulst
Bartender
Posts: 6587
86
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't think there are strict rules about when a thread has to write data through to an object, outside of synchronization. If the language leaves this open, compilers are free to make optimizations as they see fit. Therefore, it could be different among various JVM vendors.

You should never assume anything about inter-thread visibility if the context isn't properly synchronized. Threads may write results to a cache, and the cache may flush to memory at unpredictable times. If you don't synchronize properly, the old value in the cache may overwrite a new value in main memory computed by a different thread.

Synchronization ensures that when a thread releases a lock on an object (either by leaving a synchronized block or method, or when the wait() method is called), all the state information that it still has in cache is written through to memory. Hence the keyword 'synchronized'. It effectively synchronizes a thread's view of the world with that of other threads.
 
Chris Hurst
Ranch Hand
Posts: 443
3
C++ Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

The definitive answer to all your questions is here ...

http://en.wikipedia.org/wiki/Java_Memory_Model
http://www.cs.umd.edu/~pugh/java/memoryModel/


I'll try to help with something simpler ..

Disclaimer: in answering your questions have I have to make some gross simplifications for readability i.e. if you want a definitive answer use the document above but its a tough read.
Thread flushes are more commonly called memory fence (usually CPU level except java .. lol) or memory barrier (OS, language level). All answers apply Java >= 5 only (ish ;-) ).

http://en.wikipedia.org/wiki/Memory_barrier

i) Quick answer not guaranteed (thread start/completion), though note I suspect your code is synchronized (System) see below for details.

Long answer ..

- Synchronized blocks and volatiles strictly don't have to cause memory / fence barriers but its possibly best to assume they do if your struggling with the topic,
- They do guarantee "happens before ordering" which encompasses more eg Memory barriers (thread flushes) aren't the only issue you also need to prevent certain compiler/hotspot optimisations which have similar effects e.g.
shuffling your bye code (reordering).
- You can't guarantee a memory barrier / fence in java (Doug Lea has added a java fence api for Java 7).
- If the JVM decides a memory barrier is unecessary (optimisation for speed) it doesn't have to use one i.e. write to volatile variable guarantees happens before ordering not memory barrier i.e. a volatile int could be an int ;-)
Write to volatile doesn't guarantee write to main memory (strictly).

http://www.ibm.com/developerworks/java/library/j-jtp10185/index.html

Optimisation (as opposed to thread flush) problem example ...

What your code looks like (globalVar is a global non volatile boolean) ...



the equivalent java your actually running ...



If globalVar is volatile this optimisation would not be allowed (good).


ii) To work out what your code guarantees you need to need to identify sequence points, the obvious first one is thread start a new thread (thread pools make this topic harder) can see all (volatile) writes prior to its creation.
It then looks like you have none .... BUT .. what about the implementation of System.out.println ?? if you look a the Java source it looks like you have a common PrintStream and writes are synchronized soooo ... your two threads are
synchronized soo you have happens (writes flushed, read not cached, byte code can't be shuffled) before ordering (note the println could be preventing bugs ... eek)


iii) If two threads sync on THE SAME OBJECT any writes by either of the syncing threads (only) that happen before the synchronization are guaranteed to be visible to the other thread. If you have a third thread altering the same variables with no sync things get very complicated ;-)
your basically hinting as to what happens when you mix in non volatile writes from a third thread and the answer is if you try it I'd guess all most all the time you would see the results BUT categorically you can not rely on this behaviour.
Two threads syncing would not force a third CPU to uncachce using your terminology, it could do but it doesn't have to its basically what ever works best for Java it can do. Strictly any non volatile writes by the third thread thread are not guaranteed to happen before any read (volatile or not) of the first two.


Imagine three computers share the same cloud memory and have three threads one per PC (This actually exists see http://www.terracotta.org/ and this obeys the JMM) so in effect you have three copies of the same variable (they'll actually be lots more CPU caches etc) , now when your thread sync an IP conversation is initiated that will resolve any
difference between the first two but the third can hide all its writes (non volatile) to the same variable and also ignore any writes of the other two (non volatile read).
 
Chris Hurst
Ranch Hand
Posts: 443
3
C++ Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Synchronization ensures that when a thread releases a lock on an object (either by leaving a synchronized block or method, or when the wait() method is called), all the state information that it still has in cache is written through to memory.


Strictly this is not true, synchronized for instance guarantees happens before ordering not how that will be achieved, consider this example for instance ...

Why does this matter consider this trick that was several people to attempt a memory barrier / cache flush ...



The idea being you have created a memory barrier but actually such an effect is only a potential side effect of a synchronized block and not guaranteed.
Consider Lock Elision ..

From ...
http://www.ibm.com/developerworks/java/library/j-jtp10185/index.html

It stands to reason, then, that if a thread enters a synchronized block protected by a lock that no other thread will ever synchronize on, then that synchronization has no effect and can therefore be removed by the optimizer. (The Java Language Specification explicitly allows this optimization.)




(Apologies if I'm being picky ;-) )
 
Raul Gupta
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks a lot guys for the reply!

Help is much appreciated!


 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!