Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will Java's synchronization update the complete cache, or only the object I synchronized on?

If I access an object inside of a synchronized method or synchronized block, are all object in that accessed element also synchronized?

Imagine there's an object Queue having a synchronized add() and take() method, accepting and handing out the complex object Thing. Thing has a lot of lists with other different objects in it.

Now image thread Before creates Thing and puts some existing objects into Thing, modifies some of these object and so on. The Before thread adds Thing to Queue. A bit later thread After takes the Thing from Queue.

QUESTION: Will Thing and all its children/subobject be in the same state as Before left them in? Even if thread After was maybe working on one of these subelements a bit earlier? Because I image the processor for thread After might still have some cached information on that subelement (the address of that subobject is still the same). All this cached stuff would be invalidated only through accessing the father object Thing in a synchronized way?

Please don't give answers like use the concurrency libs etc. I want to understand what is going on.

like image 245
Franz Kafka Avatar asked Aug 28 '11 10:08

Franz Kafka


2 Answers

The important concept in Java's memory model is the happens-before order. Results of write actions which happen-before read actions are visible to these read actions. Other results may or may not be visible.

The happen-before order is induced by synchronization order of actions between threads, and by the natural order of actions in the individual threads.

If you in Before synchronize on an object (e.g. your Queue), and do all of your manipulations of Thing and its "subobjects" inside or before this synchronized-block, and After synchronized on the same Queue and reads these objects in or after the synchronized-block, then all those changes are visible to After.

like image 112
Paŭlo Ebermann Avatar answered Oct 14 '22 18:10

Paŭlo Ebermann


If a thread modifies a variable, another thread is not guaranteed to see the changes except in the following cases (well, at least in the following cases; I'm not 100% sure if there are more):

  • the modifying thread leaves a synchronized block or method; this induces a flush of the thread cache (likewise a thread that enters a synchronized block or method induces a refresh) -- this is what happens in your case
  • the modified variable is declared volatile or it is one of the atomic variables from java.util.concurrent.atomic
  • the modifying thread finishes (this also induces a flush, likewise the start of a thread induces a refresh)

So if you synchronize as you explained, other threads will see all changes.

like image 33
musiKk Avatar answered Oct 14 '22 17:10

musiKk