mardi 26 novembre 2019

C++ std::atomic - impossibility of synchronizing 2 threads based on a shared atomic variable

In my program, 2 threads sort a simple array in a contradictory (for test) way. The single idea is to prevent both threads to sort the array at the same time using std::atomic. The expected result is that the array will be sorted, either descending or ascending depending on "the winner thread". I know that this can easily be solved with mutexes, but I just here try to understand the benefit of std::atomic. My program fails in 10% of all execution cases: failure is when both sorts intertwine... Thanks in advance for any highlighting...

std::array my_array{ 1, 4, 3, 2, 5 }; std::atomic< std::array* > my_array_{ &my_array };

std::thread my_thread(
    [&my_array_]() {
        std::array<int, 5>* my_array = nullptr;
        do { my_array = my_array_.load(std::memory_order_acquire); } while (my_array == nullptr);
        my_array_.store(nullptr, std::memory_order_release);

        std::sort(my_array->begin(), my_array->end(),
            [](const int a, const  int b) {
                // std::cout << "\tascending a: " << a << " b: " << b << std::endl;
                return a > b;
            });
        my_array_.store(my_array, std::memory_order_release);
    });

std::thread my_thread_(
    [&my_array_]() {
        std::array<int, 5>* my_array = nullptr;
        do { my_array = my_array_.load(std::memory_order_acquire); } while (my_array == nullptr);
        my_array_.store(nullptr, std::memory_order_release);

        std::sort(my_array->begin(), my_array->end(),
            [](const int a, const int b) {
                // std::cout << "\tdescending a: " << a << " b: " << b << std::endl;
                return a < b;
            });
        my_array_.store(my_array, std::memory_order_release);
    });

my_thread_.join();
my_thread.join();

for (const int i : my_array)
    std::cout << "\t" << i;

Aucun commentaire:

Enregistrer un commentaire