Domanda

In the following code example, program execution never ends.

It creates a thread which waits for a global bool to be set to true before terminating. There is only one writer and one reader. I believe that the only situation that allows the loop to continue running is if the bool variable is false.

How is it possible that the bool variable ends up in an inconsistent state with just one writer?

#include <iostream>
#include <pthread.h>
#include <unistd.h>

bool done = false;

void * threadfunc1(void *) {
    std::cout << "t1:start" << std::endl;
    while(!done);
    std::cout << "t1:done" << std::endl;

    return NULL;
}

int main()
{
    pthread_t threads;

    pthread_create(&threads, NULL, threadfunc1, NULL);

    sleep(1);

    done = true;
    std::cout << "done set to true" << std::endl;

    pthread_exit(NULL);

    return 0;
}
È stato utile?

Soluzione

There's a problem in the sense that this statement in threadfunc1():

   while(!done);

can be implemented by the compiler as something like:

       a_register = done;
   label:
       if (a_register == 0) goto label;

So updates to done will never be seen.

Altri suggerimenti

There is really nothing that prevents the compiler from optimizing the while-loop away. Use atomic or a mutex to access the bool from more than one thread. That is the only supported and correct solution. As you are using posix, a mutex would be the right solution in this case.

And don't use volatile. There is a posix standard that states what has to work and volatile is not a solution that has a guaranty to work.

And there is an othere problem: There is no guaranty that your newly created thread every started to run, before you set the flag to false.

For such simple example volatile is enough. But for vast majority of real world situations it is not. Use conditional variable for this task. They look weird at the first glance but actually they are quite logical. On x86 bool IS atomic to read/write (for ARM, probably, not). Also there is an obstacle with vector: it is NOT a vector of bools, it is a bitfield. To write vector from several threads use vector (or bool arr[SIZE]). Also you don't join with thread, it is wrong.

Race condition means: when two threads are accessing the same object, and at least one of them is a write.

It means you will have two types of racing, write-write conflict and write-read conflict.

Back to your code, you essentially have two threads, one is the main thread, and another one is the one you created with pthread_create.

One of them is a read: while(!done), and one of them is a write: done = true.

You have race condition for sure.

Is a race condition possible when only one thread writes to a bool variable in c++?

Yes. In your case, the main thread is also a thread (i.e. you have one thread writing and one thread reading).

How is it possible that the bool variable ends up in an inconsistent state with just one writer?

The compiler is (should be) an optimizing compiler. It will probably optimize the reading of the done variable, unless you take care to avoid that (use std::atomic<bool> done instead).

its not guaranteed that the assignment to a bool which is one byte is atomic

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top