In the previous chapter, we touched on the basics of concurrency and multithreading in C++. One of the biggest challenges in concurrent code design is properly handling data races. Thread synchronization and orchestration is not an easy topic to grasp, although we might consider it the most important one. While we can use synchronization primitives such as mutexes everywhere that we have the slightest doubt about a data race, it's not a best practice that we would advise.
A better way of designing concurrent code is to avoid locks at all costs. That would not only increase the performance of the application but also make it much safer than before. Easier said than done – lock-free programming is a challenging topic that we are introducing in this chapter. In particular, we will go further into the fundamentals of designing lock...