2010-09-01 1 views
3
>>> l = Lock() 
>>> l.acquire() 
True 
>>> l.release() 
>>> l.release() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: semaphore or lock released too many times 

вызывает исключение ValueError. Как я могу предотвратить выпуск блокировки более одного раза? Что-то вроде l.is_released()?Как узнать, выпущен ли многопроцессор Python.Lock или нет?

+1

Как правило, вы просто пишете свой код, чтобы он не пытался освободить блокировку больше, чем она была получена ... – Amber

+0

Это может включать использование флага is_the_lock_locked? –

ответ

6

Вопрос немного неясен. Вам нужно использовать семафоры вместо блокировок или проверить, заблокирован ли замок.

Замки Python не такие, как блокировки на .Net, например. Блокировка Python однажды разблокирует релизы ВСЕ другие потоки, которые приобрели() на одной и той же блокировке и заблокированы на данный момент. Любой поток может освобождаться, и все идет одновременно. Таким образом, вместо того, чтобы делать вторую разблокировку, выполните

if l.locked(): 
    l.release() 

Если вы хотите «очередь» поведение, где только один Протектор получит право собственности на замке сразу несколько других релизов, использовать семафор, событие или какой-либо другой подобный класс, который позволяет вложенные блокировки и поведение в очереди.

Интересно отметить, что другие языки/loolkits, такие как .Net, делают блокировку в очереди, где потоки могут накапливать блокировку.захвата по порядку, блокировать и владеть объектом блокировки в порядке очереди на покупку, а не отпустите все сразу.

(Изменить: забыли поставить родителей как в «если l.locked: l.realse()». Исправлен код. Lock.locked подтвержден как настоящий метод в cPython 2.6.x, 3.x, IronPython 2.6.1)

+7

>>> от многопроцессорной импорта блокировки >>> блокировки() заблокирована Traceback (самый последний вызов последнего): Файл "", строка 1, в AttributeError: объект 'Lock' не имеет атрибута 'запертой' –

+1

Вы можете сделать неблокирующее получение как в «not lock.acquire (False)», проверяя код возврата. – kristopolous

6

Ожидается, что контекст, который приобрел блокировку, должен быть осведомлен о том, когда он должен ее освободить. В каком случае вы попытаетесь выпустить его несколько раз?

+0

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

+2

Либо сделайте попытку более подробной или воспользуйтесь контекстными менеджерами (с помощью my_lock :), чтобы гарантировать освобождение вашей блокировки. . –

0

Поскольку lock.acquire() возвращает true, если он успешно получает блокировку, вы можете сохранить состояние блокировки в локальной переменной и затем инкапсулировать lock.acquire() и последующий код внутри попытки - окончательно блокировать. Затем в блоке finally вы можете запросить переменную, чтобы узнать, была ли обнаружена блокировка или нет. Если он есть, отпустите.

Смежные вопросы