Dr. Dobb's Journal - February 2009 - (Page 40) d02sutt_p2db 12/12/08 9:05 AM Page 40 Effective Concurrency by Herb Sutter volatile vs. volatile A tale of two similar but different tools WHAT DOES THE volatile keyword mean? How should you use it? Confusingly, there are two common answers, because depending on the language you use volatile supports one or the other of two different programming techniques: lock-free programming, and dealing with “unusual” memory. (See Figure 1.) Adding to the confusion, these two different uses have overlapping requirements and impose overlapping restrictions, which makes them appear more similar than they are. Let’s define and understand them clearly, and see how to spell them correctly in C, C++, Java and C#—and not always as volatile. port in Java 5 (2004). Java additionally provides a few named types in java.util.concurrent.atomic, such as AtomicLongArray, that you can use for the same purpose. • .NET mostly added them in Visual Studio 2005, also under the volatile keyword (e.g., volatile int). These are suitable for nearly all lock-free code uses, except for rare examples similar to Dekker’s algorithm. .NET is fixing these remaining corner cases in Visual Studio 2010, which is in early beta as of this writing. • ISO C++ added them to the C++0x draft Standard in 2007, under the templated name atomic (e.g., atomic ). They started to become available beginning in 2008 in the Boost project and other implementations. [2] The ISO C++ atomics library also provides a C-compatible way to spell those types and their operations (e.g., atomic_int), and these appear to be likely to be adopted by ISO C in the future. Case 1: Ordered Atomic Variables For Lock-Free Programming Lock-free programming is all about doing communication and synchronization between threads using lowerlevel tools than mutex locks. In the past and even today, however, these tools are all over the map. In rough historical order, they include explicit fences/barriers (e.g., Linux’s mb()), order-inducing special API calls (e.g., Windows’ InterlockedExchange), and various flavors of special atomic types. Many of these tools are tedious and/or difficult, and their wide variety means that lockfree code ends up being written differently in different environments. The last few years, however, have seen a major convergence across hardware and software vendors: The computing industry is coalescing around sequentially consistent ordered atomic variables as the default or only way to write lock-free code using the major languages and OS platforms. In a nutshell, ordered atomic variables are safe to read and write on multiple threads at the same time without doing any explicit locking because they provide two guarantees: their reads and writes are guaranteed to be executed in the order they appear in your program’s source code; and each read or write is guaranteed to be atomic, all-or-nothing. They also have special operations such as compareAndSet that are guaranteed to be executed atomically. See [1] for further details about ordered atomic variables and how to use them correctly. Ordered atomic variables are available in Java, C# and other .NET languages, and the forthcoming ISO C++ Standard, but under different names: • Java provides ordered atomics under the volatile keyword (e.g., volatile int), and solidified this sup40 Dr. Dobb’s Journal l www.ddj.com l February 2009 A Word About Optimization We’re going to look at how ordered atomics restrict the optimizations that compilers, CPUs, cache effects, and other parts of your execution environment might perform. So let’s first briefly review some basic rules of optimization. The most fundamental rule of optimization in pretty much any language is this: Optimizations that rearrange (“transform”) your code’s execution are always legal if they don’t change the meaning of the program, so that the program can’t tell the difference between executing the original code and the transformed code. In some languages, this is also known as the “as if” rule—which gets its name from the fact that the transformed code has the same observable effects “as if” the original source code had been executed as written. This rule cuts two ways: First, an optimization must never make it possible to get a result that wasn’t possible before, or break any guarantees that the original code was allowed to rely on, including language semantics. If we produce an impossible result, after all, the program and the user certainly can tell the difference, and it’s not just “as if” we’d executed the original untransformed code. Second, optimizations are permitted to reduce the set of possible executions. For example, an optimization might make some potential (but not guaranteed) interleavings never actually happen. This is okay, because the program couldn’t rely on them happening anyway. Ordered Atomics and Optimization Using ordered atomic variables restricts the kinds of optimizations your compiler and processor and cache system can do. [3] There are two kinds of optimizations to consider: • Optimizations on the ordered atomic reads and writes themselves. • Optimizations on nearby ordinary reads and writes. First, all of the ordered atomic reads and writes on a given thread must execute exactly in source code order, because that’s one of the fundamental guarantees of ordered atomic variables. However, we can still perform some optimizations, in particular, optimizations that have the same effect as if this thread just always executed so quickly that another thread didn’t happen to ever interleave at certain points. http://www.ddj.com
Table of Contents Feed for the Digital Edition of Dr. Dobb's Journal - February 2009 Dr. Dobb's Journal - February 2009 Contents Friday Night Fish Fry Alia Vox Developer Diaries Conversations Computing in the Clouds Software Development in the Cloud Videos and Oracle Forms 10g Parallel LINQ Decoupling C Header Files Effective Concurrency Disciplined Agility Swaine’s Flames Dr. Dobb's Journal - February 2009 Dr. Dobb's Journal - February 2009 - (Page BB1) Dr. Dobb's Journal - February 2009 - (Page BB2) Dr. Dobb's Journal - February 2009 - Dr. Dobb's Journal - February 2009 (Page Cover1) Dr. Dobb's Journal - February 2009 - Dr. Dobb's Journal - February 2009 (Page Cover2) Dr. Dobb's Journal - February 2009 - Dr. Dobb's Journal - February 2009 (Page 1) Dr. Dobb's Journal - February 2009 - Dr. Dobb's Journal - February 2009 (Page 2) Dr. Dobb's Journal - February 2009 - Dr. Dobb's Journal - February 2009 (Page 3) Dr. Dobb's Journal - February 2009 - Contents (Page 4) Dr. Dobb's Journal - February 2009 - Contents (Page 5) Dr. Dobb's Journal - February 2009 - Friday Night Fish Fry (Page 6) Dr. Dobb's Journal - February 2009 - Friday Night Fish Fry (Page 7) Dr. Dobb's Journal - February 2009 - Friday Night Fish Fry (Page 8) Dr. Dobb's Journal - February 2009 - Friday Night Fish Fry (Page 9) Dr. Dobb's Journal - February 2009 - Alia Vox (Page 10) Dr. Dobb's Journal - February 2009 - Alia Vox (Page 11) Dr. Dobb's Journal - February 2009 - Developer Diaries (Page 12) Dr. Dobb's Journal - February 2009 - Developer Diaries (Page 13) Dr. Dobb's Journal - February 2009 - Conversations (Page 14) Dr. Dobb's Journal - February 2009 - Conversations (Page 15) Dr. Dobb's Journal - February 2009 - Computing in the Clouds (Page 16) Dr. Dobb's Journal - February 2009 - Computing in the Clouds (Page 17) Dr. Dobb's Journal - February 2009 - Computing in the Clouds (Page 18) Dr. Dobb's Journal - February 2009 - Computing in the Clouds (Page 19) Dr. Dobb's Journal - February 2009 - Computing in the Clouds (Page 20) Dr. Dobb's Journal - February 2009 - Computing in the Clouds (Page 21) Dr. Dobb's Journal - February 2009 - Software Development in the Cloud (Page 22) Dr. Dobb's Journal - February 2009 - Software Development in the Cloud (Page 23) Dr. Dobb's Journal - February 2009 - Software Development in the Cloud (Page 24) Dr. Dobb's Journal - February 2009 - Software Development in the Cloud (Page 25) Dr. Dobb's Journal - February 2009 - Software Development in the Cloud (Page 26) Dr. Dobb's Journal - February 2009 - Software Development in the Cloud (Page 27) Dr. Dobb's Journal - February 2009 - Videos and Oracle Forms 10g (Page 28) Dr. Dobb's Journal - February 2009 - Videos and Oracle Forms 10g (Page 29) Dr. Dobb's Journal - February 2009 - Videos and Oracle Forms 10g (Page 30) Dr. Dobb's Journal - February 2009 - Videos and Oracle Forms 10g (Page 31) Dr. Dobb's Journal - February 2009 - Parallel LINQ (Page 32) Dr. Dobb's Journal - February 2009 - Parallel LINQ (Page 33) Dr. Dobb's Journal - February 2009 - Parallel LINQ (Page 34) Dr. Dobb's Journal - February 2009 - Parallel LINQ (Page 35) Dr. Dobb's Journal - February 2009 - Decoupling C Header Files (Page 36) Dr. Dobb's Journal - February 2009 - Decoupling C Header Files (Page 37) Dr. Dobb's Journal - February 2009 - Decoupling C Header Files (Page 38) Dr. Dobb's Journal - February 2009 - Decoupling C Header Files (Page 39) Dr. Dobb's Journal - February 2009 - Effective Concurrency (Page 40) Dr. Dobb's Journal - February 2009 - Effective Concurrency (Page 41) Dr. Dobb's Journal - February 2009 - Effective Concurrency (Page 42) Dr. Dobb's Journal - February 2009 - Effective Concurrency (Page 43) Dr. Dobb's Journal - February 2009 - Disciplined Agility (Page 44) Dr. Dobb's Journal - February 2009 - Disciplined Agility (Page 45) Dr. Dobb's Journal - February 2009 - Disciplined Agility (Page 46) Dr. Dobb's Journal - February 2009 - Disciplined Agility (Page 47) Dr. Dobb's Journal - February 2009 - Swaine’s Flames (Page 48) Dr. Dobb's Journal - February 2009 - Swaine’s Flames (Page Cover3) Dr. Dobb's Journal - February 2009 - 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.