Download presentation
Presentation is loading. Please wait.
Published byJasper Anderson Modified over 9 years ago
1
CSC 480 - Multiprocessor Programming, Spring, 2012 Chapter 7 – Cancellation & Shutdown Dr. Dale E. Parson, week 9-10
2
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.
3
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.
4
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.
5
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.
6
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.
7
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.
8
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.
9
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.
10
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.
11
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 ; }
12
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.
13
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.
14
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); }}
15
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.
16
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.
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.