Assume you have a Collection(ConcurrentLinkedQueue) of Runnables with mutable state. Thread A iterates over the Collection and hands the Runnables to an ExecutorService. The run() method changes the Runnables state. The Runnable has no internal synchronization.
The above is a repetitive action and the worker threads need to see the changes made by previous iterations. So a Runnable gets processed by one worker thread after another, but is never accessed by more than one thread at a time -> a case of serial thread confinement(i hope ;)).
The question: Will it work just with the internal synchronization of the ConcurrentLinkedQueue/ExecutorSerivce?
To be more precise: If Thread A hands Runnable R to worker thread B and B changes the state of R, and then A hands R to worker thread C..does C see the modifications done by B?
EDIT: Also because of the quite different answers this question keeps me busy...from JCIP, 16.2.2 Safe publication, p. 346:
[...] If thread A places X on a BlockingQueue(and no thread subsequently modifies it) and thread B retrieves it from the queue, B is guaranteed to see X as A left it. This is because the BlockingQueue implementations have sufficient internal synchronization to ensure that the put happens-before the take.[...]
So because of how ExecutorService is implemented, the only guarantee given is that the worker threads always see the Runnables as the submitting thread left them.
Back to my scenario. First A hands R to B via ExecutorService, everything is fine, B sees an up-to-date R("BlockingQueue guarantee"). Now B modifies R and then A hands it to C. So what is needed is R as B left it. But what we get is R as A left it.
The changes done in B are not guaranteed to be visible in A, even when B finishes executing R before A hands it to the ExecutorService. There is no synchronization between A and B after R was run. Perhaps B loaded a variable to some sort of local cache and updated it there.
So if A does not see the current state of R after B executed it, how can C? What is missing is the safe publication from the worker threads back to A.
If I should be wrong, that would mean that modifications done by B are visible to A altough B does not do synchronization besides the take. Where hides that guarantee?