2012-01-10 33 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