Re: Mutable Objects and Thread Boundaries
Alan Gutierrez wrote:
[...]
I recall seeing something like this earlier today.
public void foo(int number) {
final List<Integer> list = new ArrayList<Integer>();
list.add(number);
new Thread(new Runnable() {
final List<Integer> happensAfter = list;
public void run() {
doSomethingWithList(happensAfter);
}
}).start();
}
And I understand now that by virtue of assigning to the final in the
Runnable, that makes the call to add happen before.
If that's correct, then I feel pretty confident that I get all this.
Hmm...
JLS Ch 17 says that...
A call to start() on a thread happens-before any actions in the started
thread.
Which implies that the final member of the runnable is unnecessary since
the item was added to the array before calling Thread.start and the run
method of the runnable will happen after thread start.
Of course. Furthermore, any use of Runnable through a thread-safe API
is going to ensure that whatever happens during the initialization in
the Runnable has completed prior to the use of the Runnable itself.
The trivial case is, of course, using the Runnable in the same thread
where it's created. That's obviously true.
But even in the case where the Runnable is being used in a different
thread ? that is, some other thread will get the reference and call the
run() method ? then as long as the Runnable is passed to that thread in
a thread-safe way (and it had better be), there is necessarily some
synchronization that ensures the Runnable reference has been passed
safely. That same synchronization will establish the "happens-before"
relationship required to ensure that the initialization of the Runnable,
and indeed anything that happens before the reference is passed to the
thread, is visible to any code in the other thread that executes after
it has retrieved the reference to the Runnable.
You may notice the similarity to the previous discussion regarding the
invoke?() methods for use with the EDT. :)
Pete