Eval Lock не работает - PullRequest
       18

Eval Lock не работает

1 голос
/ 10 января 2012

Я пытаюсь получить блокировку для похожих строк ввода. Но замок не работает. Вторая блокировка для той же строки не ждет, но первая версия разрушит блокировку, поэтому вторая версия вызовет ошибку.

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

1 Ответ

3 голосов
/ 10 января 2012

Использование 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).

...