Title: C++ Concurrency in Action
Author: Anthony Williams
Publisher: Manning Publications Co.
Year: 2019 (Second Edition)
The first edition of this book came out in the year 2012 and covered the concurrency features of C++ 11. Much has happened since then. The present C++17 is significantly richer in terms of concurrency support, especially in the area of parallel algorithms. The release of the second edition of the book recently is a nice addition to the growing number of good books on C++ 17.
The book contains 11 chapters. The major difference between this edition and the earlier one is that Chapter 10 on “Parallel Algorithms” is completely new in this second edition.
The first two chapters touch upon the basics of threading, including creating threads, waiting for threads to complete, and transferring ownership of threads. There is also a brief discussion on how to determine the number of threads supported by the hardware so that one can dynamically decide the optimal number of threads to spawn.
Chapter 3 talks about the problems of sharing data across multiple threads and the typical use of mutexes to do this correctly. Some interesting, but less common, cases can be handled through the use of std::call_once() function. This is also described in this section.
Synchronizing concurrent operations is the focus of the fourth chapter. Condition variables, Futures and Promises are covered here. One of the interesting sections in this chapter is about the continuation-style concurrency as specified in the Concurrency TS. This functionality, although not yet in the standard, is available through the std::experimental namespace.
Chapter 5 covers the important topic of C++ memory model from the perspective of threading. I would even go to the extent of saying that this should have been the first chapter of the book, because everything else depends on this foundation.
Chapters 6 and 7 discuss how one can design concurrent data structures that are both thread-safe and allow genuine concurrency. Although the general advice is to use standard data structures and algorithms from the library, often times, we have to implement our own data structures that are domain specific. These two chapters explain how to achieve this.
In Chapter 8, the author gives broad guidelines on how to design concurrent code. Important concerns about performance, scalability and exception safety are discussed here. These are practical issues that a developer needs to be aware of.
Chapter 9 touches upon the finer aspects of thread management. The two key concepts covered in this chapter are thread pooling and thread interruption. Both are important and are widely used in real-world applications.
Chapter 10 is about the support for parallel algorithms in STL. This functionality is one of the major additions in C++17. Several STL algorithms, including copy, find, sort, and transform can now execute in parallel. This chapter gives examples using the different execution policies std::execution::seq, std::execution::par, std::execution::par_unseq.
Testing and debugging multithreaded code is quite a challenge. Chapter 11 covers this topic and has some useful tips.
There are 4 appendices at the end of the book. Appendix A is titled “Brief reference for some C++11 language features”. This seems a bit odd in a book that discusses concurrency as supported in C++17. The author could have added some features of C++14 and C++17 to this chapter (there is just one additional topic “Class Template Argument Deduction” compared to the previous edition).
Appendix B provides a single-page comparison of the concurrency features of “Java”, “Posix C”, “Boost Threads”, and “C++11”. This part has been retained as it is from the First edition. I would have liked it if it had been updated to the current standard, and some additional languages included (for example, concurrency in C#, go, etc.).
Appendix C contains the complete source code for the message-passing framework and ATM example discussed earlier in the book. I am surprised that even this code is identical to the earlier version. The author could have used this larger example to showcase some of the newer concurrency features covered in the book.
The last appendix, spanning 150 pages, is a reference to the C++ thread library. Although it can be handy when you are reading the book, I personally prefer the online reference, for example, this.
Overall, this is a very useful and readable book, one that every C++ developer must have. However, having read the first edition, I feel the author could have added some more useful material in this revised edition; it feels like he was in a hurry to release the book because it was already overdue. Of course, if you do not have the first edition, now is the best time to get this revised edition.
Have a nice weekend!
Recent Comments