Dr. Dobb's Journal - November 2007 - (Page 57) d11sutt_p6ma 9/10/07 11:28 AM Page 57 by Herb Sutter Effective Concurrency Apply Critical Sections Consistently Guaranteeing mutual exclusion on shared variables THE CRITICAL SECTION is our One True Tool for guaranteeing mutual exclusion on mutable shared variables. Table 1 summarizes several common ways to express exclusive critical sections (see last month’s column [1] for details). A useful way to think about the synchronization in your program is as a daisy-chain of these “releaseacquire” handoffs that stitch all the threads’ critical sections together into some linear order, so that each one “acquires” the cumulative work done and is “released” by all the others that preceded it. Like most tools, these must be applied consistently, and with the intended meanings. A program must ensure that every use of a mutable shared object is properly protected using exactly one of these mechanisms at any given point in its lifetime. Chaos can erupt if code tries to avoid or invert these meanings (e.g., trying to abuse taking a lock or reading an atomic variable as a “critical section exit” operation; see Example 3), or tries to use inconsistent synchronization techniques at the same time. Let’s consider some examples to illustrate the proper and improper uses of critical sections, to get us used to looking for where the critical sections’ synchronization points should appear in the code. mut.lock(); queue.push( done ); mut.unlock(); cv.notify(); // enter critical section // add sentinel value; that’s all folks // exit critical section On the consumption side, the Consumer threads each pull individual tasks off the completed queue. Here, myTask is an ordinary variable local to each Consumer: // K Consumer threads // myTask = null; while( myTask != done ) { mut.lock(); while( queue.empty() ) cv.wait( mut ); myTask = queue.first(); if( myTask != done ) queue.pop(); mut.unlock(); if( myTask != done ) DoWork( myTask ); } // // // // // // // enter critical section if nothing’s there, to avoid busy-waiting we’ll release and reenter critical section take a copy of the task remove it from queue unless it was the sentinel, which we want to leave there for others to see exit critical section Example 1: One Producer, Many Consumers, Using Locks Imagine we have a single Producer thread that produces a number of tasks for Consumer threads to perform. The Producer pushes the tasks into a shared queue, and finally pushes a special done sentinel to mark the end of the work. The queue object is protected at all times using mutex mut, which the Producer holds only as long as necessary for a single push, so that Consumers can start executing their tasks concurrently with the Producer. For further efficiency, to avoid making the Consumers busy-wait whenever the queue is initially or temporarily empty, the Producer will also signal condition variable cv every time something has been added to the queue: // One Producer thread // while( ThereAreMoreTasks() ) { task = AllocateAndBuildNewTask(); mut.lock(); // enter critical section queue.push( task ); // add new task mut.unlock(); // exit critical section cv.notify(); } All of these critical sections are easy to see. This code simply protects the data structure using the same mutex for its entire shared lifetime, and it’s easy to check that you did it right—just look to make sure the code only refers to queue when inside some critical section that holds a lock on mut. The primary expression of critical sections is the explicit locking done on the mutex. The condition variable is just icing on the cake—an optimization that lets us express an efficient wait point in the middle of a locked section so that the Consumer race cars don’t have to expend needless energy spinning their tires (in this case, their lock/unlock loop) while waiting for the Producer to give them the green light. Synchronization Type Locks To Enter a Critical Section Acquire lock To Exit a Critical Section Release lock Notes Preferred, despite their drawbacks [2] Useful with locks to Condition variables Wait for cv wait point in the Notify cv express an efficient middle of a locked Semaphores Acquire semaphore Release semaphore section Use judiciously; significant care required Use judiciously, significant care required Avoid, difficult to use correctly and usually nonportable Ordered atomics (e.g., Java/.NET volatile, C++0x atomic ) Unordered atomics and explicit fences (e.g., aligned integers and Linux mb or Win32 MemoryBarrier) Read from variable * Write to variable ** Read from variable followed by fence Fence followed by write to variable * or equivalent, such as calling a compare-and-swap function having at least acquire semantics ** or equivalent, such as calling a compare-and-swap function having at least release semantics when in doubt, use a full fence Table 1: Common ways to express critical sections. November 2007 l www.ddj.com l Dr. Dobb’s Journal 57 http://www.ddj.com
Table of Contents Feed for the Digital Edition of Dr. Dobb's Journal - November 2007 Contents Hmmmm Alia Vox Developer Diaries Developer’s Notebook Smart Compilers - But Smart Enough? Conversations Grid-Enabling Resource-Intensive Applications Distributed Computing: Windows and Linux Adobe AIR: Desktop/Web Convergence Transparency on Demand Reusable Associations Effective Concurrency The Agile Edge Swaine’s Flames Dr. Dobb's Journal - November 2007 Dr. Dobb's Journal - November 2007 - (Page Cover1) Dr. Dobb's Journal - November 2007 - (Page Cover2) Dr. Dobb's Journal - November 2007 - (Page 1) Dr. Dobb's Journal - November 2007 - (Page 2) Dr. Dobb's Journal - November 2007 - (Page 3) Dr. Dobb's Journal - November 2007 - Contents (Page 4) Dr. Dobb's Journal - November 2007 - Contents (Page 5) Dr. Dobb's Journal - November 2007 - Hmmmm (Page 6) Dr. Dobb's Journal - November 2007 - Hmmmm (Page 7) Dr. Dobb's Journal - November 2007 - Hmmmm (Page 8) Dr. Dobb's Journal - November 2007 - Hmmmm (Page 9) Dr. Dobb's Journal - November 2007 - Alia Vox (Page 10) Dr. Dobb's Journal - November 2007 - Alia Vox (Page 11) Dr. Dobb's Journal - November 2007 - Developer Diaries (Page 12) Dr. Dobb's Journal - November 2007 - Developer Diaries (Page 13) Dr. Dobb's Journal - November 2007 - Developer’s Notebook (Page 14) Dr. Dobb's Journal - November 2007 - Developer’s Notebook (Page 15) Dr. Dobb's Journal - November 2007 - Smart Compilers - But Smart Enough? (Page 16) Dr. Dobb's Journal - November 2007 - Smart Compilers - But Smart Enough? (Page 17) Dr. Dobb's Journal - November 2007 - Smart Compilers - But Smart Enough? (Page 18) Dr. Dobb's Journal - November 2007 - Smart Compilers - But Smart Enough? (Page 19) Dr. Dobb's Journal - November 2007 - Conversations (Page 20) Dr. Dobb's Journal - November 2007 - Conversations (Page 21) Dr. Dobb's Journal - November 2007 - Grid-Enabling Resource-Intensive Applications (Page 22) Dr. Dobb's Journal - November 2007 - Grid-Enabling Resource-Intensive Applications (Page 23) Dr. Dobb's Journal - November 2007 - Grid-Enabling Resource-Intensive Applications (Page 24) Dr. Dobb's Journal - November 2007 - Grid-Enabling Resource-Intensive Applications (Page 25) Dr. Dobb's Journal - November 2007 - Grid-Enabling Resource-Intensive Applications (Page 26) Dr. Dobb's Journal - November 2007 - Grid-Enabling Resource-Intensive Applications (Page 27) Dr. Dobb's Journal - November 2007 - Grid-Enabling Resource-Intensive Applications (Page 28) Dr. Dobb's Journal - November 2007 - Grid-Enabling Resource-Intensive Applications (Page 29) Dr. Dobb's Journal - November 2007 - Distributed Computing: Windows and Linux (Page 30) Dr. Dobb's Journal - November 2007 - Distributed Computing: Windows and Linux (Page 31) Dr. Dobb's Journal - November 2007 - Distributed Computing: Windows and Linux (Page 32) Dr. Dobb's Journal - November 2007 - Distributed Computing: Windows and Linux (Page 33) Dr. Dobb's Journal - November 2007 - Distributed Computing: Windows and Linux (Page 34) Dr. Dobb's Journal - November 2007 - Distributed Computing: Windows and Linux (Page 35) Dr. Dobb's Journal - November 2007 - Adobe AIR: Desktop/Web Convergence (Page 36) Dr. Dobb's Journal - November 2007 - Adobe AIR: Desktop/Web Convergence (Page 37) Dr. Dobb's Journal - November 2007 - Adobe AIR: Desktop/Web Convergence (Page 38) Dr. Dobb's Journal - November 2007 - Adobe AIR: Desktop/Web Convergence (Page 39) Dr. Dobb's Journal - November 2007 - Adobe AIR: Desktop/Web Convergence (Page 40) Dr. Dobb's Journal - November 2007 - Adobe AIR: Desktop/Web Convergence (Page 41) Dr. Dobb's Journal - November 2007 - Transparency on Demand (Page 42) Dr. Dobb's Journal - November 2007 - Transparency on Demand (Page 43) Dr. Dobb's Journal - November 2007 - Transparency on Demand (Page 44) Dr. Dobb's Journal - November 2007 - Transparency on Demand (Page 45) Dr. Dobb's Journal - November 2007 - Transparency on Demand (Page 46) Dr. Dobb's Journal - November 2007 - Transparency on Demand (Page 47) Dr. Dobb's Journal - November 2007 - Transparency on Demand (Page 48) Dr. Dobb's Journal - November 2007 - Transparency on Demand (Page 49) Dr. Dobb's Journal - November 2007 - Transparency on Demand (Page 50) Dr. Dobb's Journal - November 2007 - Reusable Associations (Page 51) Dr. Dobb's Journal - November 2007 - Reusable Associations (Page 52) Dr. Dobb's Journal - November 2007 - Reusable Associations (Page 53) Dr. Dobb's Journal - November 2007 - Reusable Associations (Page 54) Dr. Dobb's Journal - November 2007 - Reusable Associations (Page 55) Dr. Dobb's Journal - November 2007 - Reusable Associations (Page 56) Dr. Dobb's Journal - November 2007 - Effective Concurrency (Page 57) Dr. Dobb's Journal - November 2007 - Effective Concurrency (Page 58) Dr. Dobb's Journal - November 2007 - Effective Concurrency (Page 59) Dr. Dobb's Journal - November 2007 - The Agile Edge (Page 60) Dr. Dobb's Journal - November 2007 - The Agile Edge (Page 61) Dr. Dobb's Journal - November 2007 - The Agile Edge (Page 62) Dr. Dobb's Journal - November 2007 - The Agile Edge (Page 63) Dr. Dobb's Journal - November 2007 - Swaine’s Flames (Page 64) Dr. Dobb's Journal - November 2007 - Swaine’s Flames (Page Cover3) Dr. Dobb's Journal - November 2007 - Swaine’s Flames (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.