Tuesday, April 24, 2012

Information on the C++11 Memory Model

I've been receiving a number of inquiries about where to turn for information about the C++11 memory model (technically the memory consistency model).  Having prepared and given a talk on the topic at last year's C++ and Beyond, I can tell you that the C++11 memory model is one of the most technically challenging topics I've ever tried to master. The good news is that if your goal is simply to write well-behaved multithreaded programs, you don't need to know any of the details of the memory model.  All you need to remember is to avoid data races in your programs, and the simplest way to do that is to follow the advice that multithreaded developers have been following for years:  access shared mutable data only when you know you have exclusive access to it, typically by acquiring a mutex before the access and releasing the mutex after the access. C++11 offers RAII classes to automate the release part of this protocol (std::lock_guard and std::unique_lock), so this is easier than ever to do. In C++11, you can also use atomic data types (e.g., std::atomic<bool>) to ensure exclusive access with often greater efficiency, but conceptually these are just data types where, on each access, C++ itself handles the moral equivalent of locking and unlocking the appropriate mutex.  (In practice, special machine instructions that avoid the need for mutexes are typically employed.) So, as I said, if your interest in the C++11 memory model is to know how to write threaded programs that will run correctly, you can essentially ignore the model itself.

If, on the other hand, you really want to understand the memory model, you have your work cut out for you.  Under no conditions should you start with the C++11 Standard!  Without the proper protective gear in place, that thing could maim you for life. Instead, I suggest you start with Anthony Williams' book, C++ Concurrency in Action.  Chapter 5 has the most comprehensible description of the C++11 memory model I have seen, and in fact it's the only one I know of that points out that C++11 actually offers three different consistency models:  sequential consistency, acquire-release consistency, and relaxed consistency.  (That alone should give you some idea of what you're in for if you decide to delve into this topic.) I own Williams' book in both electronic and paper form, and I think it's not just the best current treatment of C++11's threading facilities (including, but not limited to, the memory  model), it's likely to remain the best for some time to come.

Sources that complement Williams' coverage include the following.  Note that anything published before September 2011 may differ from the final C++11 memory model, and the longer the time before September 2011, the higher the likelihood of divergence.
Good luck!


Dan said...

Thanks for the information and the pointers (no pun intended) of where to look for more information.

I write low-level software (much of it in C++, in spite of Linus' advice to the contrary), so this information is very useful.

In the process of writing code, I continually shift from wanting to understand the underlying model, to simply wanting to know that I'm writing solid, safe code that uses the languages features (e.g.,
std::lock_guard, std::atomic like you mentioned.)

I've heard good things about the Williams book, and I've got a long flight coming up and a Kindle Fire with unused capacity, time to go shopping!

Michal Mocny said...

After nearly two years of waiting for my preorder, this book landed on my doorstep a month ago, and it has been an absolute pleasure to read so far (I've covered just past half of it).

I must admit, I skipped over chapter 5 to jump ahead to a few things I found more immediately interesting (thread pools, task libraries, etc), esp. since I don't plan on writing lock free data structures any time soon.

Still, I am looking forward to finally scratching the itch of figuring out the C++11 memory model :)