Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread Pool, Shared Data, Java Synchronization

Say, I have a data object:

class ValueRef { double value; }

Where each data object is stored in a master collection:

Collection<ValueRef> masterList = ...;

I also have a collection of jobs, where each job has a local collection of data objects (where each data object also appears in the masterList):

class Job implements Runnable { 
     Collection<ValueRef> neededValues = ...; 
     void run() {
         double sum = 0;
         for (ValueRef x: neededValues) sum += x;
         System.out.println(sum);
     } 
}

Use-case:

  1. for (ValueRef x: masterList) { x.value = Math.random(); }

  2. Populate a job queue with some jobs.

  3. Wake up a thread pool

  4. Wait until each job has been evaluated

Note: During the job evaluation, all of the values are all constant. The threads however, have possibly evaluated jobs in the past, and retain cached values.

Question: what is the minimal amount of synchronization necessary to ensure each thread sees the latest values?

I understand synchronize from the monitor/lock-perspective, I do not understand synchronize from the cache/flush-perspective (ie. what is being guaranteed by the memory model on enter/exit of the synchronized block).

To me, it feels like I should need to synchronize once in the thread that updates the values to commit the new values to main memory, and once per worker thread, to flush the cache so the new values are read. But I'm unsure how best to do this.

My approach: create a global monitor: static Object guard = new Object(); Then, synchronize on guard, while updating the master list. Then finally, before starting the thread pool, once for each thread in the pool, synchronize on guard in an empty block.

Does that really cause a full flush of any value read by that thread? Or just values touched inside the synchronize block? In which case, instead of an empty block, maybe I should read each value once in a loop?

Thanks for your time.


Edit: I think my question boils down to, once I exit a synchronized block, does every first read (after that point) go to main memory? Regardless of what I synchronized upon?

like image 674
Raffy Avatar asked Jun 26 '12 20:06

Raffy


1 Answers

It doesn't matter that threads of a thread pool have evaluated some jobs in the past.

Javadoc of Executor says:

Memory consistency effects: Actions in a thread prior to submitting a Runnable object to an Executor happen-before its execution begins, perhaps in another thread.

So, as long as you use standard thread pool implementation and change the data before submitting the jobs you shouldn't worry about memory visibility effects.

like image 135
axtavt Avatar answered Sep 19 '22 16:09

axtavt