Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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;
}
like image 539
xslr Avatar asked Jan 17 '14 10:01

xslr


People also ask

Can a race condition occur within a single process?

Short: A race condition can only occur between two or more threads / external state (one of them can be the OS). We cannot have race conditions inside a single thread process, non I/O doing program.

Which of the following can cause a race condition?

When race conditions occur. A race condition occurs when two threads access a shared variable at the same time. The first thread reads the variable, and the second thread reads the same value from the variable.

What is a race condition and how do you avoid them?

To avoid race conditions, any operation on a shared resource – that is, on a resource that can be shared between threads – must be executed atomically. One way to achieve atomicity is by using critical sections — mutually exclusive parts of the program.

What is race condition in multithreading and how can it be resolved?

A race condition occurs when two or more threads can access shared data and they try to change it at the same time. Because the thread scheduling algorithm can swap between threads at any time, you don't know the order in which the threads will attempt to access the shared data.


Video Answer


3 Answers

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.

like image 153
Michael Burr Avatar answered Oct 25 '22 04:10

Michael Burr


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.

like image 41
Torsten Robitzki Avatar answered Oct 25 '22 03:10

Torsten Robitzki


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.

like image 2
Aleksandr Pakhomov Avatar answered Oct 25 '22 03:10

Aleksandr Pakhomov