Home > database >  In the example of std::atomic<T>::exchange, why the count of times is not 25?
In the example of std::atomic<T>::exchange, why the count of times is not 25?

Time:06-25

The example I talked about is this one on cppreference.com. The code snippet is pasted below.

int main(){
    const std::size_t ThreadNumber = 5;
    const int Sum = 5;
    std::atomic<int> atom{0};
    std::atomic<int> counter{0};
 
    // lambda as thread proc
    auto lambda = [&](const int id){
        for (int next = 0; next < Sum;){
            // each thread is writing a value from its own knowledge
            const int current = atom.exchange(next);
            counter  ;
            // sync writing to prevent from interrupting by other threads
            std::osyncstream(std::cout)
                << '#' << id << " (" << std::this_thread::get_id()
                << ") wrote " << next << " replacing the old value "
                << current << '\n';
            next = std::max(current, next)   1;
        }
    };
 
    std::vector<std::thread> v;
    for (std::size_t i = 0; i < ThreadNumber;   i){
        v.emplace_back(lambda, i);
    }
 
    for (auto& tr : v){
        tr.join();
    }
 
    std::cout << ThreadNumber << " threads adding 0 to "
              << Sum << " takes total "
              << counter << " times\n";
}

To me, the value of counter is 25 because 5 threads and each thread loops 5 times. However, the shown output is 16. I also ran it myself, the possible value varies, but it never gets to be 25.

Why the printed value of counter is actually smaller?

CodePudding user response:

Consider one of the possible executions:

Lets say one of the threads finishes the loop before other threads start.

This gives you atom == 4. The next thread to enter the loop will get current == 4 and will exit the loop after the first iteration.

This way the second thread increments current once instead of 5 times like you expect it to.

CodePudding user response:

I haven't taken the trouble to analyse the code in detail, but the for loop in the lambda is broken (or, at least, not doing what you are expecting it to do). If you replace it with something more straightforward, namely:

for (int next = 0; next < Sum;   next){

then 25 is output.

  • Related