From: Joshua Cranmer on
On 07/20/2010 10:06 PM, Alan Gutierrez wrote:
> It was all the talk about the importance of immutability that made me
> worry that field assignments that were unsynchronized or non-volatile
> could be hidden from the receiving thread. This bit of documentation
> that I missed, plus a first reading of JLS Ch 17, put that to rest.

Immutability is the easiest way to guarantee safe publication: final
fields guarantee that they can be used by any thread safely. Any other
type of object has to be safely published. Java Concurrency in Practice
lists four ways of doing it:
* Initializing an object reference from a static initializer
* Storing a reference to it into a volatile field or AtomicReference
* Storing a reference to it into a final field of a properly constructed
object
* Storing a reference to it into a field that is properly guarded by a lock.

It also mentions that Java's thread-safe libraries all constitute safe
publication, because of their internal synchronization. To be clear, the
following are explicitly mentioned:
Hashtable, Collections.synchronizedMap, ConcurrentMap, Vector,
CopyOnWriteArrayList,CopyOnWriteArraySet, Collections.synchronizedList,
Collections.synchronizedSet, BlockingQueue, and ConcurrentLinkedQueue.

One key thing to note is that this safe publication only guarantees
visibility of changes made to an object before publication; anything
that happens afterwords must still be handled using regular
thread-safety techniques.

--
Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth
From: markspace on
Alan Gutierrez wrote:

> With a terminal value to shutdown the queue, and with the thread
> unexposed to the client, there seems to be no way to send an interrupt
> to the thread, so it becomes the classic unreachable checked exception
> block.


See, I'd go the other way. Even though I don't personally know any way
your thread is exposed to a client either, I'd still let an interrupt
kill the thread. Two reasons for this:

1) There may be some way a client can send a SIGHUP or similar through
the console, which the JVM might propagate to all threads, for an
orderly shutdown (kill -9 is disorderly and abrupt).

2) Another programmer might assume that any thread can be killed with an
interrupt, and might be confused or frustrated when it can't. In this
light, it's just a bit of future proofing and courtesy to make your
thread work in the standard way.

This is not to say that there is never a good reason to ignore
interrupts, just that one shouldn't do so without a good reason.
From: Alan Gutierrez on
Joshua Cranmer wrote:
> On 07/20/2010 10:06 PM, Alan Gutierrez wrote:
>> It was all the talk about the importance of immutability that made me
>> worry that field assignments that were unsynchronized or non-volatile
>> could be hidden from the receiving thread. This bit of documentation
>> that I missed, plus a first reading of JLS Ch 17, put that to rest.
>
> Immutability is the easiest way to guarantee safe publication: final
> fields guarantee that they can be used by any thread safely. Any other
> type of object has to be safely published. Java Concurrency in Practice
> lists four ways of doing it:
> * Initializing an object reference from a static initializer
> * Storing a reference to it into a volatile field or AtomicReference
> * Storing a reference to it into a final field of a properly constructed
> object
> * Storing a reference to it into a field that is properly guarded by a
> lock.
>
> It also mentions that Java's thread-safe libraries all constitute safe
> publication, because of their internal synchronization. To be clear, the
> following are explicitly mentioned:
> Hashtable, Collections.synchronizedMap, ConcurrentMap, Vector,
> CopyOnWriteArrayList,CopyOnWriteArraySet, Collections.synchronizedList,
> Collections.synchronizedSet, BlockingQueue, and ConcurrentLinkedQueue.
>
> One key thing to note is that this safe publication only guarantees
> visibility of changes made to an object before publication; anything
> that happens afterwords must still be handled using regular
> thread-safety techniques.

Very cool. Thank you.

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.

--
Alan Gutierrez - alan(a)blogometer.com - http://twitter.com/bigeasy
From: ClassCastException on
On Tue, 20 Jul 2010 21:19:58 -0500, Alan Gutierrez wrote:

> With a terminal value to shutdown the queue, and with the thread
> unexposed to the client, there seems to be no way to send an interrupt
> to the thread, so it becomes the classic unreachable checked exception
> block. How do you handle the interrupt that never happens? I decided
> that trying again after the impossible was as good as giving into the
> impossible.

My usual way of handling an "unreachable" checked exception block is
"throw new Error();".

If the "unreachable" checked exception block ever IS reached, then the
code did not behave the way I anticipated it would. The code contains a
bug of some sort; it's not doing what I thought it would. Something is
allowed to happen (reaching that block) that I thought was prevented.
More things may be allowed to happen (e.g., data corruption) that I
thought was prevented, too.

Ignoring the exception, or even closing the one thread down silently,
would not raise the alarm; it would mask the symptom or, at best, replace
it with a subtler and less specific symptom (logging thread silently and
mysteriously terminates).

Throwing an Error, preferably with the InterrutpedException chained to it
as a cause, will produce a stack trace in the console for me to examine
that may reveal much about what's happening, including how an assumed
unreachable block got reached. The stack trace will also point to which
such location got reached; I can add breakpoints or other debugging code
in there and try to reproduce the bug to get more information and get a
step closer to its source, in this case, to where the
InterruptedException came from that shouldn't have been possible (by
adding an e.printStackTrace(); in the catch block, say -- indeed, I might
put that there and then throw new Error(); to begin with -- and then
looking for the throw of the InterruptedException in its stack trace).
From: Alan Gutierrez on
Alan Gutierrez wrote:
> Joshua Cranmer wrote:
>> On 07/20/2010 10:06 PM, Alan Gutierrez wrote:
>>> It was all the talk about the importance of immutability that made me
>>> worry that field assignments that were unsynchronized or non-volatile
>>> could be hidden from the receiving thread. This bit of documentation
>>> that I missed, plus a first reading of JLS Ch 17, put that to rest.
>>
>> Immutability is the easiest way to guarantee safe publication: final
>> fields guarantee that they can be used by any thread safely. Any other
>> type of object has to be safely published. Java Concurrency in
>> Practice lists four ways of doing it:
>> * Initializing an object reference from a static initializer
>> * Storing a reference to it into a volatile field or AtomicReference
>> * Storing a reference to it into a final field of a properly
>> constructed object
>> * Storing a reference to it into a field that is properly guarded by a
>> lock.
>>
>> It also mentions that Java's thread-safe libraries all constitute safe
>> publication, because of their internal synchronization. To be clear,
>> the following are explicitly mentioned:
>> Hashtable, Collections.synchronizedMap, ConcurrentMap, Vector,
>> CopyOnWriteArrayList,CopyOnWriteArraySet,
>> Collections.synchronizedList, Collections.synchronizedSet,
>> BlockingQueue, and ConcurrentLinkedQueue.
>>
>> One key thing to note is that this safe publication only guarantees
>> visibility of changes made to an object before publication; anything
>> that happens afterwords must still be handled using regular
>> thread-safety techniques.
>
> Very cool. Thank you.
>
> 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.

--
Alan Gutierrez - alan(a)blogometer.com - http://twitter.com/bigeasy