multithreading - Is this python code thread safe (thread with twisted)? -
i writing application collect udp messages , process them every 1sec.
application prototype looks like:
from twisted.internet.protocol import datagramprotocol twisted.internet import reactor import threading import time class udplistener(datagramprotocol): messages = [] def datagramreceived(self, data, (host, port)): self.messages.append(data) class messenger(threading.thread): listener = none def __init__(self): threading.thread.__init__(self) def run(self): while true: time.sleep(1) recivedmessages = self.listener.messages length = len(recivedmessages) messagestoproccess = recivedmessages[0:length] #dosomethingwithmessages(messagestoproccess) del self.listener.messages[0:length] print(length) listener = udplistener() messenger = messenger() messenger.listener = listener messenger.start() reactor.listenudp(5556, listener) reactor.run()
i not sure if can remove beginning values list (del self.listener.messages[0:length]) without risk incoming message changes list , application crashes.
update - version lock
class messenger(threading.thread): listener = none lock = threading.lock() def __init__(self): threading.thread.__init__(self) def run(self): while true: time.sleep(1) recivedmessages = self.listener.messages self.lock.acquire() try: length = len(recivedmessages) messagestoproccess = recivedmessages[0:length] del self.listener.messages[0:length] except exception e: raise e finally: self.lock.release() #dosomethingwithmessages(messagestoproccess) print(length)
your code isn't thread-safe, no. you'd need have lock around messages
.
however, don't need thread here. why not this?
from twisted.internet.protocol import datagramprotocol twisted.internet import reactor class udplistener(datagramprotocol): callinglater = false messages = [] def process(self): dosomethingwithmessages(self.messages) self.messages = [] self.callinglater = false def datagramreceived(self, data, (host, port)): self.messages.append(data) if not self.callinglater: reactor.calllater(1.0, self.process) self.callinglater = true listener = udplistener() reactor.listenudp(5556, listener) reactor.run()
update: here how original version work lock, educational purposes only. note not efficient , more prone bugs. edit: separated message logic out udplistener
classes using don't need know gooey internal details.
from twisted.internet.protocol import datagramprotocol twisted.internet import reactor import threading import time class udplistener(datagramprotocol): message_lock = threading.lock() messages = [] def datagramreceived(self, data, (host, port)): self.message_lock: self.messages.append(data) def getandclearmessages(self): self.message_lock: res = self.messages self.messages = [] return res class messenger(threading.thread): listener = none def __init__(self): threading.thread.__init__(self) def run(self): while true: time.sleep(1) recivedmessages = self.listener.getandclearmessages() length = len(recivedmessages) #dosomethingwithmessages(recivedmessages) print(length) listener = udplistener() messenger = messenger() messenger.listener = listener messenger.start() reactor.listenudp(5556, listener) reactor.run()
Comments
Post a Comment