C++ Concurrency in Action: Practical Multithreading

Author: Anthony Williams
All Stack Overflow 10
This Year Stack Overflow 2
This Month Stack Overflow 1


by anonymous   2019-07-21

just for your c++ pleasure, read this book, you'll find WAY more worth than the money spent, your concurrency world will get open wide
C++-Concurrency in Action Practical Multithreading
the books deal with all sort of issues and practical solutions between thread's data sharing, how to wake threads, thread pools creation and more...more...and more

here an example of sharing data between threads without using atomic or shared_locks

template<class T>
class TaskQueue
    TaskQueue& operator = (TaskQueue&) = delete;

    void Push(T value){
        std::lock_guard<std::mutex> lk(mut);
        condition.notify_one(); //if you have many threads trying to access the data at same time, this will wake one thread only

    void Get(T& value){
        std::unique_lock<std::mutex> lk(mut);
        condition.wait(lk, [this]{ return !data.empty(); }); // in this case it waits if queue is empty, if not needed  you can remove this line
        value = data.front();

    std::mutex mut;
    std::queue<T> data; //in your case change this to a std::map
    std::condition_variable condition;
by anonymous   2019-07-21

in c++ 11, yes. include the thread header, then start building your multi-threaded application a book worth reading, is c++ concurrency in action it will teach you how to deal with the issue of race conditions, how to make thread safe containers and very important, how to create your threadpool class

by anonymous   2019-07-21

If you want to scale linearly across more than about 8 cores you need to look at lock-free algorithms. This means implement compare-and-swap methods for the data you need to share between the threads.

There is a great book by Anthony Williams, C++ Concurrency in Action: Practical Multithreading that will show you some of the ideas.

by anonymous   2018-03-19

Here is one important difference in their usage as explained in Anthony Williams's book:

Consider this example where a condition variable is waited with a timeout:

std::condition_variable cv;
bool done;
std::mutex m;

bool wait_loop()
    auto const timeout= std::chrono::steady_clock::now()+
    std::unique_lock<std::mutex> lk(m);
    return done;

This is the recommended way to wait for condition variables with a time limit, if you’re not passing a predicate to the wait. This way, the overall length of the loop is bounded. As you saw in section 4.1.1, you need to loop when using condition variables if you don’t pass in the predicate, in order to handle spurious wakeups. If you use wait_for() in a loop, you might end up waiting almost the full length of time before a spurious wake, and the next time through the wait time starts again. This may repeat any number of times, making the total wait time unbounded.

IMO, this is one such scenario where wait_for can't replace wait_until so easily, because of its resetting nature.

by anonymous   2017-09-11
@MartinBonner Not right now, no. I have to dig a little. I remember reading this somewhere; probably in [this book](https://www.amazon.com/C-Concurrency-Action-Practical-Multithreading/dp/1933988770). On another note (not defending not providing a reference, but just for the sake of a fruitful discussion), how else can this be done? How can you ensure atomicity (done/not done with no intermediate state) without a global lock?
by litb   2017-08-20


Introductory, no previous programming experience

Introductory, with previous programming experience

* Not to be confused with C++ Primer Plus (Stephen Prata), with a significantly less favorable review.

Best practices



Reference Style - All Levels

C++11/14 References:

  • The C++ Standard (INCITS/ISO/IEC 14882-2011) This, of course, is the final arbiter of all that is or isn't C++. Be aware, however, that it is intended purely as a reference for experienced users willing to devote considerable time and effort to its understanding. As usual, the first release was quite expensive ($300+ US), but it has now been released in electronic form for $60US.

  • The C++14 standard is available, but seemingly not in an economical form – directly from the ISO it costs 198 Swiss Francs (about $200 US). For most people, the final draft before standardization is more than adequate (and free). Many will prefer an even newer draft, documenting new features that are likely to be included in C++17.

  • Overview of the New C++ (C++11/14) (PDF only) (Scott Meyers) (updated for C++1y/C++14) These are the presentation materials (slides and some lecture notes) of a three-day training course offered by Scott Meyers, who's a highly respected author on C++. Even though the list of items is short, the quality is high.

  • The C++ Core Guidelines (C++11/14/17/…) (edited by Bjarne Stroustrup and Herb Sutter) is an evolving online document consisting of a set of guidelines for using modern C++ well. The guidelines are focused on relatively higher-level issues, such as interfaces, resource management, memory management and concurrency affecting application architecture and library design. The project was announced at CppCon'15 by Bjarne Stroustrup and others and welcomes contributions from the community. Most guidelines are supplemented with a rationale and examples as well as discussions of possible tool support. Many rules are designed specifically to be automatically checkable by static analysis tools.

  • The C++ Super-FAQ (Marshall Cline, Bjarne Stroustrup and others) is an effort by the Standard C++ Foundation to unify the C++ FAQs previously maintained individually by Marshall Cline and Bjarne Stroustrup and also incorporating new contributions. The items mostly address issues at an intermediate level and are often written with a humorous tone. Not all items might be fully up to date with the latest edition of the C++ standard yet.

  • cppreference.com (C++03/11/14/17/…) (initiated by Nate Kohl) is a wiki that summarizes the basic core-language features and has extensive documentation of the C++ standard library. The documentation is very precise but is easier to read than the official standard document and provides better navigation due to its wiki nature. The project documents all versions of the C++ standard and the site allows filtering the display for a specific version. The project was presented by Nate Kohl at CppCon'14.

Classics / Older

Note: Some information contained within these books may not be up-to-date or no longer considered best practice.

by anonymous   2017-08-20

Futures are both present in the upcoming standard (C++0x) and inside boost. Note that while the main name future is the same, you will need to read into the documentation to locate other types and to understand the semantics. I don't know Java futures, so I cannot tell you where they differ, if they do.

The library in boost was written by Anthony Williams, that I believe was also involved in the definition of that part of the standard. He has also written C++ Concurrency in Action, that includes a good description of futures, tasks, promises and related objects. His company also sells a complete and up to implementation of the C++0x threading libraries, if you are interested.

by anonymous   2017-08-20

There's actually a paragraph (3.2.6) in the book explaining that the code is virtually equivalent and you could replace one with the other. The only difference being is that std::unique_lock tends to take more space and is a fraction slower than std::lock_guard.

Bottom line is whenever you don't need the additional flexibility that std::unique_lock provides, go with std::lock_guard.

by anonymous   2017-08-20

However on cache-coherent architectures visibility is ensured automatically and atomicity of 8, 16, 32 and 64 bit variables MOV operation is guaranteed.

Unless you strictly adhere to the requirements of the C++ spec to avoid data races, the compiler is not obligated to make your code function the way it appears to. For example:

int a = 0, b = 0; // shared variables, initialized to zero

a = 1;
b = 1;

Say you do this on your fully cache-coherent architecture. On such hardware it would seem that since a is written before b no thread will ever be able to see b with a value of 1 without a also having that value.

But this is not the case. If you have failed to strictly adhere to the requirements of the C++ memory model for avoiding data races, e.g. you read these variables without the correct synchronization primitives being inserted anywhere, then your program may in fact observe b being written before a. The reason is that you have introduce "undefined behavior" and the C++ implementation has no obligation to do anything that makes sense to you.

What may be going on in practice, is that the compiler may reorder writes even if the hardware works very hard to make it seem as if all writes occur in the order of the machine instructions performing the writes. You need the entire toolchain to cooperate, and cooperation from just the hardware, such as strong cache coherency, is not sufficient.

The book C++ Concurrency in Action is a good source if you care to learn about the details of the C++ memory model and writing portable, concurrent code in C++.

by anonymous   2017-08-20

The speed of iterator incrementing is O(1) for both containers, although you might get somewhat better cache locality from std::unordered_map.

Apart from the slower O(log N) find/insert/erase functionality of std::map, one other difference is that std::map provides bidirectional iterators, whereas the faster (amortized O(1) element access) std::unordered_map only provides forward iterators.

The excellent book C++ Concurrency in Action: Practical Multithreading by Anthony Williams provides a code example of a multithreaded unordered_map with a lock per entry. This book is highly recommended if you are doing serious multithreaded coding.