samedi 24 février 2018

Confused by memory order release sequence example

In the book C++ Concurrency in Action Sect 5.3.4, an example of one producer and two consumers is given to demonstrate release sequence.

#include <atomic>
#include <thread>

std::vector<int> queue_data;
std::atomic<int> count;

void populate_queue()
{
    unsigned const number_of_items=20;
    queue_data.clear();
    for(unsigned i=0;i<number_of_items;++i)
    {
        queue_data.push_back(i);
    }

    count.store(number_of_items,std::memory_order_release);
}

void consume_queue_items()
{
    while(true)
    {
        int item_index;
        if((item_index=count.fetch_sub(1,std::memory_order_acquire))<=0)
        {
            wait_for_more_items();
            continue;
        }
        process(queue_data[item_index-1]);
    }
}

int main()
{
    std::thread a(populate_queue);
    std::thread b(consume_queue_items);
    std::thread c(consume_queue_items);
    a.join();
    b.join();
    c.join();
}

I think the example is flawed, because both consumers can read the initial value 20, and work on its own without acknowledging the other's existence, leading to data race. In other words, one consumer never loads the value stored by the other. Where have I gone wrong?

Aucun commentaire:

Enregistrer un commentaire