Prev: Const correctness (was Re: Oppinion on 'least priviledge', 'const correctness', etc.)
Next: Simple Hack To Get $2500 To Your PayPal Account.
From: Joshua Cranmer on 20 Jul 2010 22:42 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 20 Jul 2010 23:04 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 20 Jul 2010 23:10 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 20 Jul 2010 23:15 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 20 Jul 2010 23:57
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 |