Does this multithreaded list processing code have enough synchronization?

  atomic, c++, multithreading, stdatomic

I have this code in test.cpp:

#include <atomic>
#include <chrono>
#include <cstdlib>
#include <iostream>
#include <thread>

static const int N_ITEMS = 11;
static const int N_WORKERS = 4;

int main(void)
{
    int* const items = (int*)std::malloc(N_ITEMS * sizeof(*items));
    for (int i = 0; i < N_ITEMS; ++i) {
        items[i] = i;
    }

    std::thread* const workers = (std::thread*)std::malloc(N_WORKERS * sizeof(*workers));
    std::atomic<int> place(0);
    for (int w = 0; w < N_WORKERS; ++w) {
        new (&workers[w]) std::thread([items, &place]() {
            int i;
            while ((i = place.fetch_add(1, std::memory_order_relaxed)) < N_ITEMS) {
                items[i] *= items[i];
                std::this_thread::sleep_for(std::chrono::seconds(1));
            }
        });
    }
    for (int w = 0; w < N_WORKERS; ++w) {
        workers[w].join();
        workers[w].~thread();
    }
    std::free(workers);

    for (int i = 0; i < N_ITEMS; ++i) {
        std::cout << items[i] << 'n';
    }

    std::free(items);
}

I compile like so on linux:

c++ -std=c++11 -Wall -Wextra -pedantic test.cpp -pthread

When run, the program should print this:

0
1
4
9
16
25
36
49
64
81
100

I don’t have much experience with C++, nor do I really understand atomic operations. According to the standard, will the worker threads always square item values correctly, and will the main thread always print the correct final values? I’m worried that the atomic variable will be updated out-of-sync with the item values, or something. If this is the case, can I change the memory order used with fetch_add to fix the code?

Source: Windows Questions C++

LEAVE A COMMENT