我正在尝试为类似的输入字符串设置锁。但是锁不起作用。同一字符串的第二个锁不会等待,但是第一个释放将破坏该锁,因此第二个释放将引发错误。
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()
结果
$ 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
最佳答案
在此应用程序中使用eval没有意义;为什么不每个线程仅保留一个锁?
class TestThread(threading.Thread):
def __init__(self, input):
threading.Thread.__init__(self)
self.input = input
self.lock = threading.Lock()
def run(self):
self.lock.acquire()
print("waste some time for %s" % self.input)
time.sleep(5)
print("%s done" % self.input)
self.lock.release()
您提到要对相同的字符串具有相同的锁,但是在那种情况下,当然,当一个字符串的锁结束时,使用相同字符串的其他线程的锁也将终止。也许,如果您更多地说明了自己的动机,我可以建议另一种解决方案。
ETA:如果您确定对于特定的应用程序,您希望对相同的字符串拥有相同的锁,那么这将是一种实现方法:
LOCK_DICT = {}
LOCK_DICT_LOCK = threading.RLock()
class TestThread(threading.Thread):
def __init__(self, input):
threading.Thread.__init__(self)
self.input = input
with LOCK_DICT_LOCK:
if self.input not in LOCK_DICT:
LOCK_DICT[self.input] = threading.Lock()
def run(self):
with LOCK_DICT_LOCK:
lock = LOCK_DICT[self.input]
lock.acquire()
print("waste some time for %s" % self.input)
time.sleep(5)
print("%s done" % self.input)
lock.release()
请注意,此特定版本使用全局变量,这不是理想的设计,但是比上面的设计中使用
eval
更好(后者也将变量保留为类属性)。当然,无论使用哪种代码,都可以将LOCK_DICT和LOCK_DICT_LOCK放置在非全局位置(例如,您称为ThreadManager的类)。