Dr. Dobb's Journal - May 2008 - (Page 49) d05sutt_p4as 3/13/08 10:42 AM Page 49 by Herb Sutter Effective Concurrency Interrupt Politely Violence isn’t the answer WE WANT TO BE ABLE to stop a running thread or task when we discover that we no longer need or want to finish it. As we saw in the last two columns, in a simple parallel search we can stop other workers once one finds a match, and when speculatively running two alternative algorithms to compute the same result we can stop the longer-running one once the first finds a result. [1,2] Stopping threads or tasks lets us reclaim their resources, including locks, and apply them to other work. But how do you stop a thread or task you longer need or want? Table 1 summarizes the four main ways, and how they are supported on several major platforms. Let’s consider them in turn. from one valid state to another. For example, data may be partly written into a buffer; or a money-transferring task may have taken money out of one account and not yet put it into the target account. Now mix in compiler optimizers, processors, and cache subsystems that routinely transform your code and execute it out of order, and you typically have no idea just from reading the source code what memory values might be read or written, and in what orders, and therefore, no way to predict the consequences of interrupting that execution at a random point. Killing a thread or task in the middle of doing some work usually means that we will leave behind state that has been corrupted, typically in an apparently random and unpredictable way; and/or we will lose resources the thread or task held, such as any locks it held. Consider for a moment the specific issue of locks: If the killed thread was holding a lock, it’s because it was using (and possibly changing) some data protected by that lock. Killing it in that state has two possible outcomes. First, on some platforms, the lock is released, which makes corrupted state visible to other parts of the program. Second, on other platforms, the lock is not released, which will deadlock any other parts of the program that are already waiting, or subsequently try to wait, for that same lock. Perhaps surprisingly, the second outcome is usually better, because at least it prevents the rest of the system from seeing the data that was left in a corrupt state. Of course, better still is not pulling the trigger and corrupting the data in the first place. In short: Please, let’s stop the slaughter. Option 1 is nearly always wrong because it is likely to corrupt at least the entire process, and might also corrupt other processes—including even processes on other machines if the killed thread was in the middle of performing some important I/O. Most of the time when someone tries to use pthread_kill, Thread.stop, and their ilk, the programmer is unaware of the extreme measure they’re really signing up for. Be aware, and don’t use it unless you really intend to take down the process or the machine without any attempt at graceful cleanup. There are two use cases where Option 1 can be appropriate, one rare and one very rare: • If you can prove that the target thread is doing nothing but reading memory and that it owns no resources, it may be safe to kill it. • If you deliberately intend to terminate and restart the entire target process (not just thread) and possibly even the entire target machine, without even trying to clean up corrupted state, then killing may be appropriate. For example, in a system that uses three redundant and independent computers or processors that do not share data, when one misbehaves, it can be appropriate to kill and restart it in isolation. Option 1: (Thou Shalt Not) Kill The first option, which is nearly always wrong, is to kill the target thread or task immediately right in the middle of whatever it happens to be doing. This form of reckless slaughter is available in most platform APIs and frameworks, including the venerable UNIX kill -9, Pthreads’ pthread_kill (or pthread_cancel in async mode), Java Thread.destroy or Thread.stop, and .NET’s Thread.Abort. Every major platform has reinvented this trap because it seems like a simple idea at first, until you realize it’s nearly impossible to write correct code whose execution can be abruptly killed at arbitrary and unpredictable points. The main trouble with Option 1 is that it is an extreme measure with extreme consequences: There’s rarely such a thing as killing just one thread or task. Doing that is liable not only to stop that particular work, but also to corrupt the entire process and possibly other processes. Chances are, the thread will be partway through an operation where it’s taking an object or data Interlude: Cancellation/Interruption Points Unlike Option 1, all of the three remaining alternatives share one vital point in common: The target thread or task can be stopped only at well-defined points in its execution, called “cancellation points” or “interruption points” which are typ, ically when the thread is blocked doing one of the following things: Table 1: Major cancellation/interruption options. • Waiting to acquire a mutex, get a signal on a semaphore, or other synchronization. May 2008 l www.ddj.com l Dr. Dobb’s Journal 49 http://www.ddj.com
Table of Contents Feed for the Digital Edition of Dr. Dobb's Journal - May 2008 Dr. Dobb's Journal - May 2008 Contents Friday Night Fish Fry Alia Vox Developer Diaries Software Development Goes to the Movies Cat: A Functional Stack-Based Little Language Mojax: Mobile Ajax Framework Kernel-Mode Databases Getting Better Search Results Effective Concurrency The Agile Edge Dr. Dobb's Journal - May 2008 Dr. Dobb's Journal - May 2008 - Dr. Dobb's Journal - May 2008 (Page Cover1) Dr. Dobb's Journal - May 2008 - Dr. Dobb's Journal - May 2008 (Page Cover2) Dr. Dobb's Journal - May 2008 - Dr. Dobb's Journal - May 2008 (Page 1) Dr. Dobb's Journal - May 2008 - Dr. Dobb's Journal - May 2008 (Page 2) Dr. Dobb's Journal - May 2008 - Dr. Dobb's Journal - May 2008 (Page 3) Dr. Dobb's Journal - May 2008 - Contents (Page 4) Dr. Dobb's Journal - May 2008 - Contents (Page 5) Dr. Dobb's Journal - May 2008 - Friday Night Fish Fry (Page 6) Dr. Dobb's Journal - May 2008 - Friday Night Fish Fry (Page 7) Dr. Dobb's Journal - May 2008 - Friday Night Fish Fry (Page 8) Dr. Dobb's Journal - May 2008 - Friday Night Fish Fry (Page 9) Dr. Dobb's Journal - May 2008 - Alia Vox (Page 10) Dr. Dobb's Journal - May 2008 - Alia Vox (Page 11) Dr. Dobb's Journal - May 2008 - Developer Diaries (Page 12) Dr. Dobb's Journal - May 2008 - Developer Diaries (Page 13) Dr. Dobb's Journal - May 2008 - Developer Diaries (Page 14) Dr. Dobb's Journal - May 2008 - Developer Diaries (Page 15) Dr. Dobb's Journal - May 2008 - Software Development Goes to the Movies (Page 16) Dr. Dobb's Journal - May 2008 - Software Development Goes to the Movies (Page 17) Dr. Dobb's Journal - May 2008 - Software Development Goes to the Movies (Page 18) Dr. Dobb's Journal - May 2008 - Software Development Goes to the Movies (Page 19) Dr. Dobb's Journal - May 2008 - Software Development Goes to the Movies (Page 20) Dr. Dobb's Journal - May 2008 - Software Development Goes to the Movies (Page 21) Dr. Dobb's Journal - May 2008 - Cat: A Functional Stack-Based Little Language (Page 22) Dr. Dobb's Journal - May 2008 - Cat: A Functional Stack-Based Little Language (Page 23) Dr. Dobb's Journal - May 2008 - Cat: A Functional Stack-Based Little Language (Page 24) Dr. Dobb's Journal - May 2008 - Cat: A Functional Stack-Based Little Language (Page 25) Dr. Dobb's Journal - May 2008 - Cat: A Functional Stack-Based Little Language (Page 26) Dr. Dobb's Journal - May 2008 - Cat: A Functional Stack-Based Little Language (Page 27) Dr. Dobb's Journal - May 2008 - Cat: A Functional Stack-Based Little Language (Page 28) Dr. Dobb's Journal - May 2008 - Cat: A Functional Stack-Based Little Language (Page 29) Dr. Dobb's Journal - May 2008 - Mojax: Mobile Ajax Framework (Page 30) Dr. Dobb's Journal - May 2008 - Mojax: Mobile Ajax Framework (Page 31) Dr. Dobb's Journal - May 2008 - Mojax: Mobile Ajax Framework (Page 32) Dr. Dobb's Journal - May 2008 - Mojax: Mobile Ajax Framework (Page 33) Dr. Dobb's Journal - May 2008 - Mojax: Mobile Ajax Framework (Page 34) Dr. Dobb's Journal - May 2008 - Mojax: Mobile Ajax Framework (Page 35) Dr. Dobb's Journal - May 2008 - Mojax: Mobile Ajax Framework (Page 36) Dr. Dobb's Journal - May 2008 - Mojax: Mobile Ajax Framework (Page 37) Dr. Dobb's Journal - May 2008 - Kernel-Mode Databases (Page 38) Dr. Dobb's Journal - May 2008 - Kernel-Mode Databases (Page 39) Dr. Dobb's Journal - May 2008 - Kernel-Mode Databases (Page 40) Dr. Dobb's Journal - May 2008 - Kernel-Mode Databases (Page 41) Dr. Dobb's Journal - May 2008 - Kernel-Mode Databases (Page 42) Dr. Dobb's Journal - May 2008 - Kernel-Mode Databases (Page 43) Dr. Dobb's Journal - May 2008 - Getting Better Search Results (Page 44) Dr. Dobb's Journal - May 2008 - Getting Better Search Results (Page 45) Dr. Dobb's Journal - May 2008 - Getting Better Search Results (Page 46) Dr. Dobb's Journal - May 2008 - Getting Better Search Results (Page 47) Dr. Dobb's Journal - May 2008 - Getting Better Search Results (Page 48) Dr. Dobb's Journal - May 2008 - Effective Concurrency (Page 49) Dr. Dobb's Journal - May 2008 - Effective Concurrency (Page 50) Dr. Dobb's Journal - May 2008 - Effective Concurrency (Page 51) Dr. Dobb's Journal - May 2008 - The Agile Edge (Page 52) Dr. Dobb's Journal - May 2008 - The Agile Edge (Page 53) Dr. Dobb's Journal - May 2008 - The Agile Edge (Page 54) Dr. Dobb's Journal - May 2008 - The Agile Edge (Page 55) Dr. Dobb's Journal - May 2008 - The Agile Edge (Page 56) Dr. Dobb's Journal - May 2008 - The Agile Edge (Page Cover3) Dr. Dobb's Journal - May 2008 - The Agile Edge (Page Cover4)
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.