I saw examples e.g. here of using an Event
to stop a thread where I think a boolean flag would do the job.
class MyThread(threading.Thread):
def __init__(self):
self._please_stop = threading.Event()
def run(self):
while not self._please_stop.is_set():
[...]
def stop(self):
self._please_stop.set()
class MyThread(threading.Thread):
def __init__(self):
self._please_stop = False
def run(self):
while not self._please_stop:
[...]
def stop(self):
self._please_stop = True
What is the benefit of using an Event
, here? Its wait
method is not used. What makes it better than a boolean flag?
I can see the point if the same Event
is shared among several threads, but otherwise, I don't get it.
This mailing list thread suggests that Event
would be safer, but it's unclear to me why.
More precisely, I don't understand those two paragraphs:
If I understand the GIL correctly, it synchronizes all access to Python data structures (such as my boolean 'terminated' flag). If that is the case, why bother using threading.Event for this purpose?
The GIL is an implementation detail and relying on it to synchronize things for you isn't futureproof. You're likely to have lots of warning, but using threading.Event() isn't any harder, and it's more correct and safer in the long term.
I agree that using an Event
adds close to no overhead, so I can stick to that, but I'd like to understand the limits of the flag approach.
(I'm using Python3, so I'm not concerned by Python2 limitations, if any, although those would be totally worth mentioning here.)
Programming is often not just about getting the code to work today, it's about keeping it working through changes that will be made in the future.
multiprocessing
... which implements Event()
but will fail if you're just using a local variable.Semaphore()
instead of Event()
... but would be easy to implement incorrectly with variables.So, it's likely you can write multithreaded programs perfectly correctly in Python relying on how the bytecode gets interrupted and when the GIL can be released... but if I am reading and changing your code later, I'd be much happier if you used the standard synchronization primitives.
I think that the implication in the thread you quote is that setting a boolean is not necessarily an atomic operation in Python. While having a global lock on all Python objects (the GIL) makes all operations that set an attribute appear atomic for the moment, such a lock may not exist in the future. Using Event
makes the operation atomic because it uses its own lock for access.
The link for atomic is to a Java question, but it is no less relevant because of that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With