2012-01-10 68 views
1

我试图锁定类似的输入字符串。但锁不起作用。同一个字符串的第二个锁不会等待,但第一个版本会销毁该锁,因此第二个版本会引发错误。eval锁不起作用

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 

回答

3

使用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() 

你提到希望有相同的字符串相同的锁,但在这种情况下,当一个字符串的锁结束当然的,所以也适用于其他线程锁使用相同的字符串。也许如果你更多地解释你的动机,我可以提出另一种解决方案。

埃塔:如果你确定,你的特定应用,你想拥有的相同的字符串相同的锁,这将是做到这一点的一种方法:

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的类)。

+0

这正是我正在寻找的。现在我只需要了解它是如何工作的,哈哈。非常感谢大卫! – Germar 2012-01-10 21:55:03

+0

我很高兴能帮到你!再次,确保您在使用此操作之前确实想要为多个线程使用相同的锁。 – 2012-01-10 23:05:41