I’m trying to have lock’s for similar input strings. But the lock’s doesn’t work. The second lock for the same string doesn’t wait but the first release will destroy the lock so the second release will raise an error.
test.py
import threading
import time
class TestThread(threading.Thread):
def __init__(self, input):
threading.Thread.__init__(self)
self.input = input
lock_wrap = "TestThread." + self.input + " = threading.Lock()"
eval(compile(lock_wrap,'<string>','exec'))
def run(self):
acquire_wrap = "TestThread." + self.input + ".acquire()"
exec(compile(acquire_wrap,'<string>','exec'))
print("waste some time for %s" % self.input)
time.sleep(30)
print("%s done" % self.input)
release_wrap = "TestThread." + self.input + ".release()"
exec(compile(release_wrap,'<string>','exec'))
my_threads = []
while True:
input = raw_input("> ")
if input == "end":
break
thread = TestThread(input)
my_threads.append(thread)
thread.start()
for t in my_threads:
t.join()
result
$ python test.py
> foo
> waste some time for foo
bar
waste some time for bar
> foo
> waste some time for foo
foo done
bar done
foo done
Exception in thread Thread-3:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "test.py", line 19, in run
exec(compile(release_wrap,'<string>','exec'))
File "<string>", line 1, in <module>
error: release unlocked lock
Using eval for this application doesn’t make sense; why not just keep one lock per thread?
You mention wanting to have the same lock for identical strings, but in that case, of course when a lock for one string ends, so will the locks for other threads using the same string. Perhaps if you explained your motivation more I could suggest another solution.
ETA: If you’re sure that, for your particular application, you want to have the same lock for the same string, this would be one way to do it:
Note that this particular version uses global variables, which isn’t ideal design, but it is much better than using
evalas in your design above (which also kept the variables as class properties). Whatever code you use can of course put LOCK_DICT and LOCK_DICT_LOCK somewhere that isn’t global (say, a class you call ThreadManager).