I created an application using multiple threads defined in multiple class files which read and write into a "shared variable" (a dictionary).
To ensure thread-safety, I am using a Lock, and I pass it as argument to my Thread class next to my variable.
What bothers me is that two objects which are intrinsically linked have to be passed to my class, while ideally only the shared variable should be. This would reduce the code and bring greater certainty while avoiding confusion in the parameters.
Here is how my program looks:
inc_thread.pyfrom threading import Thread
class IncThread(Thread):
def __init__(self, shared_dict, lock):
Thread.__init__(self, daemon=True)
self._shared_dict = shared_dict
self._lock = lock
def run(self):
while 1:
with self._lock:
self._shared_dict['some_value'] += 1
dec_thread.py
from threading import Thread
class DecThread(Thread):
def __init__(self, shared_dict, lock):
Thread.__init__(self, daemon=True)
self._shared_dict = shared_dict
self._lock = lock
def run(self):
while 1:
with self._lock:
self._shared_dict['some_value'] -= 1
main.py
import time
from threading import RLock
from dec_thread import DecThread
from inc_thread import IncThread
if __name__ == '__main__':
lock = RLock()
shared_dict = {'some_value': 0}
t1 = DecThread(shared_dict, lock)
t2 = IncThread(shared_dict, lock)
t1.start()
t2.start()
# Ensure equity regarding wich thread started first
with lock:
shared_dict['some_value'] = 0
while 1:
print(shared_dict['some_value'])
time.sleep(1)
Is it the correct way to do it?
What I also thought:
Subclass
dict
and override get / set methods with an internal lock, but it becomes complicated when I want to set other datastructures (nesteddict
,list
,set
, etc.) as values.Using
Queue
but it does not seem to fit my needs, as it is by default blocking forput
/get
while my design is more of "fire and forget".
class LockedDict
that contains the lock and whose__getitem__
,__setitem__
and__delitem__
use before delegating to thedict
equivalent methods? You can even define a mixin that you can use with whatever container you like, likeclass LockedDict(Locked, dict): pass
. \$\endgroup\$ – 301_Moved_Permanently Jul 13 '16 at 15:12