Временно отпустите блокировку, если она удерживается, в python - PullRequest
1 голос
/ 01 сентября 2010

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

selected_method = choose_method()
with lock:
    selected_method()

В некоторых из этих методов я иногда вызываю вспомогательную функцию, которая выполняет медленный сетевой ввод-вывод. (Давайте назовем это network_method()). Я хотел бы снять блокировку во время работы этой функции, чтобы позволить другим потокам продолжить их обработку.

Один из способов добиться этого - вызвать lock.release () и lock.acquire () до и после вызова сетевого метода. Однако я бы предпочел, чтобы методы не обращали внимания на блокировку, поскольку их много, и они все время меняются.

Я бы предпочел переписать network_method(), чтобы он проверял, удерживается ли блокировка, и если да, отпустите его перед запуском и снова получите в конце.

Обратите внимание, что network_method() иногда вызывается из других мест, поэтому он не должен освобождать блокировку, если она не находится в потоке, который ее удерживает.

Я пытался использовать метод locked() для объекта Lock, но этот метод только сообщает мне, удерживается ли блокировка, а не удерживается ли она текущим потоком.

Кстати, блокировка - это глобальный объект, и я в порядке.

Ответы [ 2 ]

1 голос
/ 01 сентября 2010

Я бы предпочел переписать network_method (), чтобы он проверял, удерживается ли блокировка, и если это так, отпустите его перед запуском и снова получите в конце.

Обратите внимание, чтоnetwork_method () иногда вызывается из других мест, поэтому она не должна снимать блокировку, если она находится не в потоке, который ее удерживает.

Это просто звучит как совершенно неправильная вещь: (

Для начала, плохо иметь функцию, которая иногда имеет какой-то другой магический побочный эффект, в зависимости от того, откуда вы ее вызываете. Это такая кошмарная вещь для отладки.

Во-вторых, блокировка должна иметь четкую семантику получения и выпуска. Если я посмотрю на код, который говорит «lock (); do_something (); unlock ();», то я ожидаю, что он будет заблокирован на время выполнения do_something (). Фактически, это также говорит мне, что do_something () требует блокировки. Если я узнаю, что кто-то написал определенную функцию do_something (), которая фактически разблокирует блокировку, которую я только что виделбыть заблокированным, я либо (а) уволить их или (б) выследить их с оружием, в зависимости от того, нахожусь ли я на позиции старшего по отношению к ним или нет.

Кстати,Блокировка - это глобальный объект, и я в порядке.

Кстати, именно поэтому глобальные переменные плохие.Если я изменяю значение, вызываю функцию, а затем снова изменяю значение, я не хочу, чтобы эта функция посередине могла выйти назад и изменить это значение непредсказуемым образом.

Мое предложениедля вас это: ваш замок находится не в том месте, или вы делаете не то, или другое.Вы говорите, что эти методы не должны запускаться одновременно, но вы на самом деле хотите, чтобы некоторые из них запускались одновременно.Тот факт, что один из них является «медленным», не может сделать приемлемым удаление блокировки - либо вам нужно взаимное исключение во время этого типа операции, чтобы оно было правильным, либо нет.Если более медленная операция действительно безопасна, когда другие нет, тогда, возможно, она не нуждается в блокировке - но это подразумевает, что блокировка должна идти внутри каждой из более быстрых операций, а не вне их.Но все это зависит от того, для чего именно предназначена блокировка.

0 голосов
/ 01 сентября 2010

Почему бы просто не сделать это?

with lock:
    before_network()
do_network_stuff()
with lock:
    after_network()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...