mardi 25 juillet 2017

Two threads accessing the same variables not getting interleaved

I wrote the following piece of code:

#include <thread>
#include <iostream>

void thread(bool &t1, bool &t2, int &nn) {
    t1 = true;
    if (!t2) {
        nn--;
    }
}

int main(int argc, char *argv[]) {
    bool t1, t2;
    int nn;
    for (std::size_t i = 0; true; ++i) {
        t1 = false;
        t2 = false;
        nn = 1;
        std::thread runner1(thread, std::ref(t1), std::ref(t2), std::ref(nn));
        std::thread runner2(thread, std::ref(t2), std::ref(t1), std::ref(nn));
        runner1.join();
        runner2.join();
        if (nn < 0) {
            std::cout << "ERROR! " << nn << ". Took " << i << " trials." << std::endl;
            return nn;
        }
    }
}

Notice that thread1 writes t1 to true and t2 checks if t2 is false to decrease nn, while thread2 does the inverted check. There should be a scheduling of these two threads in which both of them end up decreasing nn, and thus nn becomes -1.

A very similar example in Java does indeed end up exiting with an error within 10 seconds, however, this example I have left running for more than 10 minutes without any exits.

I have compiled with debug information (no optimizations, under MingW), and checked that the compiler does not optimize the thread function. I thought that it may be a problem I did not understand with using std::ref, but changing the references for pointers did not fix it either.

Why is it that this program does not fail? Do I have the wrong idea about the C++ memory model? Is there a stronger condition that Windows' threading implementation maintains?.

Aucun commentaire:

Enregistrer un commentaire