Reputation: 3693
I have a multi threaded application in Python 3 and have a setter and getter method of a list. The setter method appends an element to the list, while the getter method deletes all elements of the list after returning them.
The setter method looks like the following, which is in a larger async function:
while self.semaphor:
print("waiting...")
time.sleep(0.001)
self.semaphor=True
self.messages.append(msg)
print("appended data!")
While the getter method looks like the following:
while self.semaphor:
time.sleep(0.001)
self.semaphor = True
l = self.messages
self.messages = []
self.semaphor = False
if len(l) == 0:
return None
else:
return l
However the application crashes without any error messages (probably hidden due to multithreaded output in the command line) right after the prinst statetement "append data" - So I was wondering if the code snippets are thread safe and correct?
Upvotes: 0
Views: 1520
Reputation: 1124238
Your code is not threadsafe, because your self.semaphore
handling is not thread-safe. Two threads can read self.semaphore
as False
, before either of them have set it to True
, as thread switches can take place at any point between instructions.
What you want to use is a proper thread lock object (a semaphore is the wrong primitive to use here).
When creating your instance, set a self.messages_lock = threading.Lock()
attribute, and whenever you need to alter your messages
list, use:
with self.messages_lock:
# locked block of code, guaranteed to be thread-safe.
or
try:
while not self.messages_lock.acquire(timeout=0.01):
print("waiting...")
# locked block of code, guaranteed to be thread-safe.
finally:
self.messages_lock.release()
if you must have a thread that prints out that it is waiting for a lock.
Upvotes: 4