Upload
josephine-fischer
View
11
Download
0
Embed Size (px)
DESCRIPTION
CSC 480 - Multiprocessor Programming, Spring, 2012. Chapter 7 – Cancellation & Shutdown Dr. Dale E. Parson, week 9-10. Task cancellation. Activity is cancellable if external code can move it to completion before normal completion. (p. 135) Server or similar non-terminating activity. - PowerPoint PPT Presentation
Citation preview
CSC 480 - Multiprocessor Programming, Spring, 2012
Chapter 7 – Cancellation & ShutdownDr. Dale E. Parson, week 9-10
Task cancellation
• Activity is cancellable if external code can move it to completion before normal completion. (p. 135)
• Server or similar non-terminating activity.• Long-running computation.• Cancellable implies asynchronous notification.
– User-requested cancellation.– Time-limited activities.– Application events (e.g., first solution stops others).– Errors (e.g., file server backing database goes off line).– Shutdown.
Interruption
• Thread.currentThread() gets current thread.• interrupt() interrupts a thread object.
• Asynchronous but not preemptive.
• isInterrupted() returns some thread’s status without changing it.
• Thread.interrupted() returns current thread’s interrupt status and clears it.
• InterruptedException thrown by many blocking methods. Thrower may clear interrupted status.
Interruption for cancellation
• Calling interrupt() merely delivers a message.• Using interruption for anything but cancellation is
fragile and difficult to sustain in larger applications. (p. 138)
• Interruption is usually the most sensible way to implement cancellation. (p. 140)
• The intent is that threads running application tasks will have periodic opportunities to notice the interruption message, and know what that means.
Cancellation & Interruption Policy
• A Cancellation Policy is a plan for how an algorithm quits in the middle of its work.
• An Interruption Policy is a plan for how application threads and tasks respond to interrupt messages.
• Interruption is ultimately under the control of the application framework.• The design of an application framework must establish
how it uses interrupts to communicate with tasks.
Responding to an interrupt
• Do not interrupt() a thread unless you know its interruption policy. Interruption typically comes from elsewhere in application code.
• Library and application-neutral framework code may neither interpret nor ignore InterruptedException.
• A library method may throw the InterruptedException.• A library method may re-call interrupt() on its thread.
• Application code must handle the interrupt.• Use the cancellation and interruption policy to direct control.• Swallow InterruptedException only if that works with the policies.
Task Cancellation
• Tasks run in frameworks, e.g., ExecutorService.• submit() returns a Future; it may be cancel()d.• cancel() has mayInterruptIfRunning param.• The application-level task, if running, must
decide what to do with the optional interrupt.• Future.get throws CancellationException or
ExecutionException for abnormal termination of its task. Latter carries its original cause.
Uninterruptible I/O
• InputStream.read and OutputStream.write do not throw InterruptedException.
• Calls may block indefinitely.• close() on the underlying stream from another thread
causes IOException, but it may be dangerous.• Sending a “Poison pill” (special sentinel value) into the
stream from another thread, if possible, is safer.
• java.nio and java.nio.channels.Selectors have related issues, also support for closed-by-interrupt exceptions. See Javadoc.
Uninterruptible lock acquisition
• Explicit lock has lockInterruptibly(), but lock() and implicit synchronized locks are uninterruptible.
• If there is no cyclic dependency among locks (which leads to deadlock), the thread holding the lock must make progress, possibly via interruption, and release the lock.
• Compute-bound tasks or tasks that invoke non-interruptible methods, and that have an interruption policy, may need to poll isInterrupted() periodically.
Stopping a thread-based service
• Lifecycle methods of the service are necessary for state transitions and termination.
• The thread pool that manages the worker threads decides whether and when to interrupt them.
• The application code running in the service threads decides how to respond to interruption (policy).
• ExecutorService.shutdown• shutdown() – previously submitted tasks are executed, but no new
submissions are accepted.• shutdownNow() attempts to terminate tasks (typically via
interrupt()) and returns a list of tasks that were awaiting execution.
Poison pill
• Poison pill is a sentinel value that a producer passes to consumer(s) to signal shutdown.
• Poison pill(s) must come after all regular producer application data.• From solution #1 Input.run():
if (myburst.isEmpty()) { int remaining = pktq.decrementAndGetInputs(); if (remaining == 0) { // I was the last Input thread, send a sentinel to each // output thread. int outputcount = pktq.getOutputs(); for (int i = 0 ; i < outputcount ; i++) { pktq.enqueue(myburst); // empty list is sentinel } } return ; }
Limitations of shutdownNow
• There is no option to cancel un-started tasks while allowing started tasks to complete.
• It is possible to extend or adapt ExecutorService to interact with tasks in an application-specific way to determine which tasks are started without completion, and to stop only the unstarted ones. See 7.2.5.
• Race condition at task completion time is still likely.
Abnormal thread termination
• Possible to log a stack trace, but general purpose thread pool library classes do not own the application logs.
• Printing stack traces to System.err may be lost.
• General purpose framework (e.g., Eclipse) may catch unchecked exceptions (RuntimeException) and display a warning about the suspect integrity of the compromised application task or plug-in.
Boilerplate code for dealing with untrusted tasks (p. 162)
public void run() {Throwable thrown = null ;try {
while (! currentThread().isInterrupted()) {runTask(getTaskFromWorkQueue()); }
} catch (Throwable e) {thrown = e ;
} finally {threadExited(this, thrown);
}}
JVM shutdown and Daemon threads
• Runtime.addShutdownHook() deals with cases where a thread invokes System.exit() or a terminating signal arrives from the O.S.
• It starts a series of registered threads.• Make these thread-safe, defensive, and conservative.
• Daemon threads are never joined to the main thread. Text advises to use them sparing, perform no I/O in them. Use them for housekeeping such as managing an in-memory cache.
Finalizers
• Object.finalize() runs when the garbage collector is about to recover an object.
• Test says: “Avoid finalizers.”• Explicit try-finally blocks that close() (and
flush) output resources are safer and easier than using finalizers.
• They may be necessary for freeing resources obtained by native methods.