pythonpython-3.xmultithreadingpython-multithreadingrace-condition

Is a lock recommended in python when updating a bool in one direction in a thread, then reading it in another?


Is a lock necessary in a situation where thread 1 checks if a bool has flipped from False to True periodically within a loop, the bool being updated in thread 2?

As I understand a bool is atomic in python, it should not be possibly for the bool to be incorrectly updated or take on a garbage value like in C++ for example. Only one thread will ever update the bool, and it will only ever go from False to True (there is no position where it switches back to False). As the check is done periodically and timing is not critical, even if thread 1 reads the old value (False) while thread 2 is updating it to True, thread 1 should still be able to read the new value once thread 2 has finished on the next iteration of the loop.

Is this an incorrect understanding of this specific situation? I understand it is generally best to use locks, and I don't mind adding one, but I wonder if it would actually just be introducing more potential problems (like deadlocks) without actually solving any problem except maybe saving thread 1 from looping for one more iteration.

This is the loop in question. The two variables are being updated in another thread, and read in this one. Both are bool values starting as False and being set to True when the other threads have finished.

           while True:
                time.sleep(0.2)

                if self.joined_queries:
                    self.stop()
                    break

                if self.timeout:
                    self.stop()
                    break

There were some other threads but the answers were very general without going into specifics much, and the situation was a bit different. I would like to understand why this is a bad idea or not!

This piece of documentation makes me believe it is not a problem, but I am not really sure if I am interpreting it correctly: http://www.python.org/doc/faq/library/#what-kinds-of-global-value-mutation-are-thread-safe


Solution

  • As I understand a bool is atomic in python, it should not be possibly for the bool to be incorrectly updated or take on a garbage value like in C++ for example

    Practically, a bool variable in cPython is going to be a pointer to one of the two objects Py_True or Py_False. The implementation details shouldn't matter, but it's relevant to know that a bool in Python will be exactly as atomic as a pointer in C.

    In a cPython build without the GIL, this will be a data race and hence Undefined Behaviour according to the underlying C code.

    This piece of documentation makes me believe it is not a problem

    The page you linked explicitly says both that this sort of code is safe due to the GIL, and that work on removing the GIL to improve performance is ongoing. It seems unwise to write new code that depends on it.

    Note that C's Undefined Behaviour may be perfectly well-defined on a given hardware platform, it's just non-portable. However, the code will be brittle in the face of newer interpreters and platforms.