Spec-Zone.ru › Python 2.7

threading — Интерфейс многопоточности высокого уровня

Исходный код: Lib/threading.py

Этот модуль создаёт интерфейсы многопоточности высокого уровня на основе модуля низкого уровня thread. Также см. модули mutex и Queue.

Модуль dummy_threading предназначен для ситуаций, когда модуль threading использовать нельзя, так как отсутствует модуль thread.

Примечание

Начиная с Python 2.6, этот модуль предоставляет совместимые с PEP 8 псевдонимы и свойства для замены имён, вдохновлённых API для многопоточности Java. Этот обновлённый API совместим с API модуля multiprocessing. Однако, пока не определено расписание для устаревания имён camelCase, и они по-прежнему полностью поддерживаются как в Python 2.x, так и в 3.x.

Примечание

Начиная с Python 2.5, несколько методов класса Thread вызывают исключение RuntimeError вместо AssertionError, если их вызов ошибочен.

Примечание реализации CPython: В CPython из-за глобальной блокировки интерпретатора одновременно может выполняться только один поток Python-кода (хотя некоторые библиотеки с оптимизацией производительности могут обойти это ограничение). Если вы хотите, чтобы ваше приложение лучше использовало вычислительные ресурсы многоядерных машин, рекомендуется использовать модуль multiprocessing. Однако, многопоточность всё ещё является подходящей моделью, если вы хотите одновременно запускать несколько задач, ограниченных ввода-выводом.

В этом модуле определены следующие функции и объекты:

threading.active_count()
threading.activeCount()

Возвращает количество объектов Thread, которые в данный момент работают. Возвращаемое значение равно длине списка, возвращаемого функцией enumerate().

Изменено в версии 2.6: Добавлен вариант написания active_count().

threading.Condition()

Функция-фабрика, которая возвращает новый объект условия. Объект условия позволяет одному или нескольким потокам ожидать, пока другой поток не уведомит их.

См. Объекты условия.

threading.current_thread()
threading.currentThread()

Возвращает текущий объект Thread, соответствующий потоку управления вызывающего потока. Если поток управления вызывающего потока не был создан с помощью модуля threading, возвращается объект виртуального потока с ограниченными возможностями.

Изменено в версии 2.6: Добавлен вариант написания current_thread().

threading.enumerate()

Возвращает список всех объектов Thread, которые в данный момент работают. Список включает демонические потоки, виртуальные объекты потоков, созданные функцией current_thread(), и основной поток. Он не включает завершённые потоки и потоки, которые ещё не были запущены.

threading.Event()

Функция-фабрика, которая возвращает новый объект события. Объект события управляет флагом, который может быть установлен в значение «истина» методом set() и сброшен в значение «ложь» методом clear(). Метод wait() блокируется, пока флаг не станет «истина».

См. Объекты событий.

class threading.local

Класс, представляющий данные локальные для потока. Данные, локальные для потока, это данные, значения которых специфичны для каждого потока. Для управления данными, локальными для потока, просто создайте экземпляр local (или подкласс) и сохраните атрибуты в нём:

mydata = threading.local()
mydata.x = 1

Значения экземпляра будут разными для отдельных потоков.

Для получения более подробной информации и расширенных примеров обратитесь к строке документации модуля _threading_local.

Введено в версии 2.4.

threading.Lock()

Функция-фабрика, которая возвращает новый примитивный объект блокировки. После того как поток его получил, все последующие попытки получения блокируются, пока он не будет освобождён; любой поток может освободить его.

См. Объекты блокировок.

threading.RLock()

Функция-фабрика, которая возвращает новый объект рекурсивной блокировки. Рекурсивную блокировку должен освободить тот же поток, который её получил. После того как поток получил рекурсивную блокировку, тот же поток может получить её снова без блокировки; поток должен освободить её один раз для каждого случая получения блокировки.

См. Объекты рекурсивных блокировок.

threading.Semaphore([value])

Функция-фабрика, которая возвращает новый объект семафора. Семафор управляет счётчиком, представляющим количество вызовов release(), минус количество вызовов acquire(), плюс начальное значение. Метод acquire() блокируется, если необходимо, до тех пор, пока он не может вернуться без получения отрицательного значения счётчика. Если value не указан, по умолчанию он равен 1.

См. Объекты семафоров.

threading.BoundedSemaphore([value])

Функция-фабрика, которая возвращает новый объект ограниченного семафора. Ограниченный семафор проверяет, чтобы его текущее значение не превышало его начальное значение. Если это произойдёт, возбуждается исключение ValueError. В большинстве ситуаций семафоры используются для защиты ресурсов с ограниченной ёмкостью. Если семафор освобождается слишком много раз, это указывает на ошибку. Если value не указан, по умолчанию он равен 1.

class threading.Thread

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

См. Объекты потоков.

class threading.Timer

Поток, который выполняет функцию после того, как пройдёт заданный интервал.

См. Объекты таймеров.

threading.settrace(func)

Устанавливает функцию отслеживания для всех потоков, запущенных из модуля threading. Функция func будет передана в sys.settrace() для каждого потока перед вызовом метода run().

Введено в версии 2.3.

threading.setprofile(func)

Устанавливает функцию профилирования для всех потоков, запущенных из модуля threading. Функция func будет передана в sys.setprofile() для каждого потока перед вызовом метода run().

Введено в версии 2.3.

threading.stack_size([size])

Возвращает размер стека потока, используемый при создании новых потоков. Необязательный аргумент size задаёт размер стека для последующих созданных потоков и должен быть равен 0 (использовать платформенный или настроенный по умолчанию) или положительным целым значением не меньше 32 768 (32 КБ). Если size не указан, используется 0. Если изменение размера стека потока не поддерживается, генерируется исключение ThreadError. Если указанный размер стека некорректен, генерируется исключение ValueError, и размер стека не изменяется. 32 КБ в настоящее время являются минимальным поддерживаемым размером стека, чтобы гарантировать достаточное пространство стека для самого интерпретатора. Обратите внимание, что некоторые платформы могут иметь особые ограничения на значения размера стека, например, требовать минимальный размер стека > 32 КБ или требовать выделение кратно размеру страницы системной памяти — для получения дополнительной информации следует обратиться к документации платформы (обычно 4 КБ; рекомендуется использовать кратные 4096 для размера стека в отсутствие более конкретной информации). Доступность: Windows, системы с POSIX-потоками.

Добавлена в версии 2.5.

exception threading.ThreadError

Генерируется для различных ошибок, связанных с потоками, как описано ниже. Обратите внимание, что многие интерфейсы используют RuntimeError вместо ThreadError.

Подробные интерфейсы для объектов документированы ниже.

Конструкции этого модуля основаны на модели потоков Java. Однако там, где Java делает блокировки и переменные состояния основным поведением каждого объекта, в Python они являются отдельными объектами. Класс Python Thread поддерживает подмножество поведения класса Thread Java; в настоящее время отсутствуют приоритеты, группы потоков, и потоки нельзя уничтожать, останавливать, приостанавливать, возобновлять или прерывать. Статические методы класса Thread Java, если они реализованы, отображаются в функции уровня модуля.

Все методы, описанные ниже, выполняются атомарно.

1. Объекты потоков

Этот класс представляет активность, которая выполняется в отдельном потоке управления. Существует два способа указать активность: передав вызываемый объект в конструктор или переопределив метод run() в подклассе. Никакие другие методы (кроме конструктора) не должны переопределяться в подклассе. Другими словами, только переопределяйте методы __init__() и run() этого класса.

После создания объекта потока его активность необходимо запустить, вызвав метод start() потока. Это вызывает метод run() в отдельном потоке управления.

После запуска активности потока поток считается «живым». Он перестаёт быть живым, когда его метод run() завершается — либо нормально, либо путём подъема необработанного исключения. Метод is_alive() проверяет, жив ли поток.

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

Поток имеет имя. Имя может быть передано в конструктор и считывается или изменяется через атрибут name.

Поток может быть помечен как «поток-демон». Значение этого флага состоит в том, что вся программа Python завершается, когда остаются только потоки-демоны. Начальное значение наследуется от создающего потока. Флаг можно установить с помощью свойства daemon.

Примечание

Потоки-демоны внезапно останавливаются при завершении работы. Их ресурсы (например, открытые файлы, транзакции баз данных и т. д.) могут не быть корректно освобождены. Если вы хотите, чтобы ваши потоки завершались плавно, сделайте их не-демонскими и используйте подходящий механизм сигнализации, такой как Event.

Существует объект «главный поток»; он соответствует начальному потоку управления в программе Python. Он не является потоком-демоном.

Существует возможность создания «объектов фиктивных потоков». Это объекты потоков, соответствующие «чужеродным потокам», которые являются потоками управления, запущенными вне модуля потоков, например, непосредственно из кода C. Объекты фиктивных потоков имеют ограниченные возможности; они всегда считаются живыми и демонскими и не могут быть join(). Они никогда не удаляются, поскольку невозможно обнаружить завершение чужеродных потоков.

class threading.Thread(group=None, target=None, name=None, args=(), kwargs={})

Этот конструктор всегда должен вызываться с ключевыми аргументами. Аргументы:

group должен быть None; зарезервирован для будущих расширений, когда будет реализован класс ThreadGroup.

target — вызываемый объект, который будет вызван методом run(). По умолчанию None, то есть ничего не вызывается.

name — имя потока. По умолчанию генерируется уникальное имя в формате «Поток-N», где N — небольшое десятичное число.

args — кортеж аргументов для вызова целевого объекта. По умолчанию ().

kwargs — словарь ключевых аргументов для вызова целевого объекта. По умолчанию {}.

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

start()

Запустить активность потока.

Должен быть вызван не более одного раза на объект потока. Он организует вызов метода объекта run() в отдельном потоке управления.

Этот метод вызовет RuntimeError, если будет вызван более одного раза на том же объекте потока.

run()

Метод, представляющий активность потока.

Вы можете переопределить этот метод в подклассе. Стандартный метод run() вызывает вызываемый объект, переданный в конструктор объекта в качестве аргумента target, если таковой имеется, с последовательными и ключевыми аргументами, взятыми из аргументов args и kwargs соответственно.

join([timeout])

Ожидать завершения потока. Это блокирует вызывающий поток до тех пор, пока поток, метод join() которого вызван, не завершится — как обычно, так и из-за необработанного исключения — или пока не произойдёт опциональная задержка.

Если аргумент timeout присутствует и не None, он должен быть числом с плавающей точкой, определяющим время ожидания операции в секундах (или долях секунды). Поскольку join() всегда возвращает None, вы должны вызвать isAlive() после join(), чтобы определить, произошла ли задержка — если поток всё ещё активен, вызов join() истек по времени.

Если аргумент timeout отсутствует или None, операция будет блокироваться до завершения потока.

Поток может быть join() многократно.

Вызов join() вызывает RuntimeError, если попытка объединения текущего потока, поскольку это вызовет тупик. Также является ошибкой join() потока до его запуска, и попытки сделать это вызывают то же самое исключение.

name

Строка, используемая только для идентификации. Она не имеет семантики. Несколько потоков могут иметь одно и то же имя. Начальное имя устанавливается конструктором.

В версии 2.6.

getName()
setName()

API до версии 2.6 для name.

ident

«Идентификатор потока» этого потока или None если поток ещё не запущен. Это целое число, отличное от нуля. См. функцию thread.get_ident(). Идентификаторы потоков могут быть переиспользованы, когда поток завершается, и создаётся другой поток. Идентификатор доступен даже после завершения потока.

В версии 2.6.

is_alive()
isAlive()

Возвращает, жив ли поток.

Этот метод возвращает True сразу перед началом метода run() и до момента завершения метода run(). Функция модуля enumerate() возвращает список всех активных потоков.

Изменено в версии 2.6: Добавлено is_alive() написание.

daemon

Булево значение, указывающее, является ли этот поток демоническим потоком (True) или нет (False). Это значение должно быть установлено до вызова start(), в противном случае возникает RuntimeError. Его начальное значение наследуется от создающего потока; основной поток не является демоническим потоком, и поэтому все потоки, созданные в главном потоке, по умолчанию имеют daemon = False.

Весь интерпретатор Python завершается, когда не осталось ни одного активного не-демонического потока.

В версии 2.6.

isDaemon()
setDaemon()

API до версии 2.6 для daemon.

2. Объекты блокировок

Примитивная блокировка — это синхронизирующий примитив, который не принадлежит какому-либо конкретному потоку при блокировке. В Python в настоящее время это самый низкоуровневый доступный синхронизирующий примитив, реализованный напрямую модулем расширения thread.

Примитивная блокировка находится в одном из двух состояний: «заблокированная» или «разблокированная». Она создаётся в разблокированном состоянии. У неё есть два основных метода: acquire() и release(). Когда состояние разблокировано, acquire() меняет состояние на заблокированное и возвращает значение сразу. Когда состояние заблокировано, acquire() блокируется до тех пор, пока вызов release() в другом потоке не изменит его на разблокированное, затем вызов acquire() устанавливает его обратно в заблокированное состояние и возвращает значение. Метод release() должен вызываться только в заблокированном состоянии; он меняет состояние на разблокированное и возвращает значение сразу. Если попытка освободить разблокированную блокировку, будет поднято исключение ThreadError.

Когда несколько потоков заблокированы в acquire() в ожидании изменения состояния на разблокированное, только один поток продолжает выполнение, когда вызов release() устанавливает состояние обратно в разблокированное; какой из ожидающих потоков возобновит работу, не определено и может отличаться в различных реализациях.

Все методы выполняются атомарно.

Lock.acquire([blocking])

Приобрести блокировку, блокирующим или неблокирующим образом.

Когда вызывается с аргументом blocking установленным в True (по умолчанию), заблокироваться до тех пор, пока блокировка не будет разблокирована, затем установить её в заблокированное состояние и вернуть True.

Когда вызывается с аргументом blocking установленным в False, не блокироваться. Если вызов с blocking установленным в True заблокируется, вернуть False немедленно; в противном случае установить блокировку в заблокированное состояние и вернуть True.

Lock.release()

Освободить блокировку.

Когда блокировка заблокирована, установить её в разблокированное состояние и вернуть значение. Если другие потоки заблокированы, ожидая разблокирования, разрешить продолжение выполнения ровно одному из них.

При вызове на разблокированной блокировке возникает ThreadError.

Значение не возвращается.

3. Объекты RLock

Перевключаемая блокировка — это синхронизирующий примитив, который может быть приобретён несколько раз одним и тем же потоком. Внутренне он использует понятия «владеющий поток» и «уровень рекурсии» в дополнение к состоянию блокировки/разблокировки, используемому примитивными блокировками. В заблокированном состоянии какой-то поток владеет блокировкой; в разблокированном состоянии — нет.

Для блокировки блокировки поток вызывает её метод acquire(); это возвращает значение, как только поток приобретает владение блокировкой. Чтобы разблокировать блокировку, поток вызывает её метод release(). acquire()/release() вызовы могут быть вложенными; только последний вызов release() (последний вызов release() из внешней пары) устанавливает блокировку в разблокированное состояние и позволяет другому потоку, заблокированному в acquire(), продолжить работу.

RLock.acquire([blocking=1])

Захватить блокировку, блокирующим или неблокирующим способом.

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

При вызове с аргументом blocking, установленным в значение true, выполнить те же действия, что и при вызове без аргументов, и вернуть true.

При вызове с аргументом blocking, установленным в значение false, не блокироваться. Если вызов без аргумента заблокировал бы, вернуть false немедленно; в противном случае, выполнить те же действия, что и при вызове без аргументов, и вернуть true.

RLock.release()

Освободить блокировку, уменьшив уровень рекурсии. Если после уменьшения он равен нулю, сбросить блокировку в состояние разблокированного состояния (ни один поток не владеет ею) и, если какие-либо другие потоки заблокированы в ожидании разблокировки, разрешить ровно одному из них продолжить. Если после уменьшения уровень рекурсии по-прежнему не равен нулю, блокировка остаётся заблокированной и принадлежит вызывающему потоку.

Вызывать этот метод только когда вызывающий поток владеет блокировкой. RuntimeError генерируется, если этот метод вызывается, когда блокировка разблокирована.

Значения возврата нет.

4. Объекты условных переменных

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

Условная переменная имеет методы acquire() и release(), которые вызывают соответствующие методы связанной блокировки. Она также имеет метод wait(), и методы notify() и notifyAll(). Эти три метода должны вызываться только тогда, когда вызывающий поток захватил блокировку, в противном случае генерируется RuntimeError.

Метод wait() освобождает блокировку и затем блокируется до тех пор, пока он не будет разбужен вызовом notify() или notifyAll() для той же условной переменной в другом потоке. После пробуждения он повторно захватывает блокировку и возвращается. Также возможно указать таймаут.

Метод notify() разбуждает один из потоков, ожидающих условную переменную, если таковые есть. Метод notifyAll() разбуждает все потоки, ожидающие условную переменную.

Примечание: методы notify() и notifyAll() не освобождают блокировку; это означает, что разбуженный поток или потоки не вернутся из своего вызова wait() сразу, а только тогда, когда поток, вызвавший notify() или notifyAll(), окончательно откажется от владения блокировкой.

Подсказка: типичный стиль программирования с использованием условных переменных использует блокировку для синхронизации доступа к некоторому общему состоянию; потоки, заинтересованные в конкретном изменении состояния, вызывают wait() многократно, пока не увидят желаемое состояние, в то время как потоки, изменяющие состояние, вызывают notify() или notifyAll() при изменении состояния таким образом, что оно может быть желаемым состоянием для одного из ожидающих потоков. Например, следующий код представляет собой типичную ситуацию "производитель-потребитель" с неограниченной ёмкостью буфера:

# Consume one item
cv.acquire()
while not an_item_is_available():
    cv.wait()
get_an_available_item()
cv.release()

# Produce one item
cv.acquire()
make_an_item_available()
cv.notify()
cv.release()

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

class threading.Condition([lock])

Если аргумент lock задан и не None, он должен быть объектом Lock или RLock, и он используется в качестве базовой блокировки. В противном случае, создаётся новый объект RLock и используется в качестве базовой блокировки.

acquire(*args)

Захватить базовую блокировку. Этот метод вызывает соответствующий метод на базовой блокировке; значение возврата — то, что возвращает этот метод.

release()

Освободить базовую блокировку. Этот метод вызывает соответствующий метод на базовой блокировке; значения возврата нет.

wait([timeout])

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

Этот метод освобождает базовую блокировку и затем блокируется до тех пор, пока он не будет разбужен вызовом notify() или notifyAll() для той же условной переменной в другом потоке, или пока не наступит необязательный таймаут. После пробуждения или истечения таймаута он повторно захватывает блокировку и возвращается.

Если аргумент timeout присутствует и не None, он должен быть числом с плавающей точкой, задающим таймаут операции в секундах (или дробных частях секунды).

Если базовая блокировка — RLock, она не освобождается с помощью метода release(), поскольку это может не разблокировать блокировку, когда она была захвачена несколько раз рекурсивно. Вместо этого используется внутренний интерфейс класса RLock, который действительно разблокирует её, даже если она была захвачена рекурсивно несколько раз. Затем используется другой внутренний интерфейс для восстановления уровня рекурсии при повторном захвате блокировки.

notify(n=1)

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

Этот метод разбудит не более n потоков, ожидающих условную переменную; это не делает ничего, если нет ожидающих потоков.

Текущая реализация разбудит ровно n потоков, если хотя бы n потоков ожидают. Однако, нельзя полагаться на это поведение. Будущая, оптимизированная реализация может иногда разбудить больше чем n потоков.

Примечание: разбуженный поток фактически не возвращается из своего вызова wait() до тех пор, пока он не сможет повторно захватить блокировку. Поскольку notify() не освобождает блокировку, вызывающий поток должен это сделать.

notify_all()
notifyAll()

Разбудить все потоки, ожидающие эту условную переменную. Этот метод действует как notify(), но разбуживает все ожидающие потоки вместо одного. Если вызывающий поток не захватил блокировку при вызове этого метода, генерируется RuntimeError.

Изменено в версии 2.6: Добавлена альтернативная запись notify_all().

5. Объекты семафоров

Это одна из старейших примитивов синхронизации в истории информатики, изобретённая голландским компьютерным ученым Эдсгером В. Дейкстрой (он использовал P() и V() вместо acquire() и release()).

Семафор управляет внутренним счётчиком, который уменьшается при каждом вызове acquire() и увеличивается при каждом вызове release(). Счётчик никогда не может опуститься ниже нуля; когда acquire() обнаруживает, что он равен нулю, он блокируется, ожидая, пока какой-то другой поток вызовет release().

class threading.Semaphore([value])

Необязательный аргумент задаёт начальное значение для внутреннего счётчика; по умолчанию оно равно 1. Если заданное значение меньше 0, возникает исключение ValueError.

acquire([blocking])

Получить доступ к семафору.

При вызове без аргументов: если внутренний счётчик больше нуля, он уменьшается на единицу и функция возвращает значение немедленно. Если он равен нулю, происходит блокировка, и поток ожидает, пока другой поток не вызовет release(), чтобы сделать его больше нуля. Это делается с надлежащей блокировкой, так что, если несколько вызовов acquire() заблокированы, release() разбудит ровно один из них. Реализация может выбрать один случайным образом, поэтому порядок разбуживания заблокированных потоков не гарантируется. В этом случае значение не возвращается.

При вызове с blocking установленным в true, делается то же самое, что и при вызове без аргументов, и возвращается true.

При вызове с blocking установленным в false, блокировка не происходит. Если бы вызов без аргументов заблокировал, немедленно возвращается false; в противном случае делается то же самое, что и при вызове без аргументов, и возвращается true.

release()

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

5.1. Semaphore Пример

Семафоры часто используются для защиты ресурсов с ограниченной ёмкостью, например, базы данных сервера. В любой ситуации, где размер ресурса фиксирован, следует использовать ограниченный семафор. Перед запуском рабочих потоков основной поток инициализирует семафор:

maxconnections = 5
...
pool_sema = BoundedSemaphore(value=maxconnections)

После запуска рабочие потоки вызывают методы acquire и release семафора, когда им нужно подключиться к серверу:

pool_sema.acquire()
conn = connectdb()
... use connection ...
conn.close()
pool_sema.release()

Использование ограниченного семафора снижает вероятность того, что ошибка программирования, которая приводит к тому, что семафор освобождается чаще, чем приобретается, останется незамеченной.

6. Объекты событий

Это один из самых простых механизмов взаимодействия между потоками: один поток сигнализирует об событии, а другие потоки ожидают его.

Объект события управляет внутренней меткой, которая может быть установлена в true с помощью метода set() и сброшена до false с помощью метода clear(). Метод wait() блокирует поток до тех пор, пока метка не станет true.

class threading.Event

Внутренняя метка изначально false.

is_set()
isSet()

Возвращает true только тогда, когда внутренняя метка равна true.

Изменено в версии 2.6: Добавлена is_set() форма записи.

set()

Установить внутреннюю метку в true. Все потоки, ожидающие её установки в true, разбуживаются. Потоки, вызывающие wait() после того, как метка стала true, вообще не будут заблокированы.

clear()

Сбросить внутреннюю метку в false. Впоследствии потоки, вызывающие wait(), будут заблокированы до тех пор, пока set() не вызовет установки внутренней метки в true снова.

wait([timeout])

Заблокировать поток, пока внутренняя метка не станет true. Если внутренняя метка равна true при входе, функция возвращает значение немедленно. В противном случае поток блокируется до тех пор, пока другой поток не вызовет set() для установки метки в true, или пока не наступит заданный таймаут.

Когда аргумент таймаута присутствует и не равен None, он должен быть числом с плавающей точкой, указывающим на время ожидания операции в секундах (или долях секунды).

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

Изменено в версии 2.7: Ранее метод всегда возвращал None.

7. Объекты таймеров

Этот класс представляет действие, которое должно быть выполнено только после того, как пройдёт определённое время — таймер. Timer является подклассом Thread и, таким образом, также служит примером создания пользовательских потоков.

Таймеры запускаются, как и потоки, вызовом метода start(). Таймер можно остановить (до начала его действия) вызовом метода cancel(). Интервал ожидания таймера перед выполнением его действия может не совпадать точно с заданным пользователем интервалом.

Например:

def hello():
    print "hello, world"

t = Timer(30.0, hello)
t.start()  # after 30 seconds, "hello, world" will be printed
class threading.Timer(interval, function, args=[], kwargs={})

Создать таймер, который выполнит function с аргументами args и именованными аргументами kwargs, по истечении interval секунд.

cancel()

Остановить таймер и отменить выполнение действия таймера. Это сработает только если таймер всё ещё находится в стадии ожидания.

8. Использование блокировок, условий и семафоров в операторе with

Все объекты, предоставленные этим модулем, которые имеют методы acquire() и release() могут использоваться в качестве менеджеров контекста для оператора with. Метод acquire() будет вызван при входе в блок, а release() — при выходе из блока.

В настоящее время объекты Lock, RLock, Condition, Semaphore и BoundedSemaphore могут быть использованы в качестве менеджеров контекста оператора with. Например:

import threading

some_rlock = threading.RLock()

with some_rlock:
    print "some_rlock is locked while this executes"

9. Импортирование в многопоточном коде

Хотя механизм импорта безопасен в многопоточном режиме, существуют два ключевых ограничения для импорта в многопоточных приложениях из-за присущих ограничений механизма многопоточной безопасности:

  • Во-первых, кроме как в основном модуле, импорт не должен вызывать создание нового потока и каким-либо образом ожидать его завершения. Несоблюдение этого ограничения может привести к тупику, если запущенный поток прямо или косвенно пытается импортировать модуль.
  • Во-вторых, все попытки импорта должны быть завершены до того, как интерпретатор начнёт завершаться. Это можно наиболее легко обеспечить, выполняя импорты только из потоков, не являющихся демонами, созданных с помощью модуля threading. Демоновые потоки и потоки, созданные напрямую с помощью модуля thread, потребуют других форм синхронизации, чтобы гарантировать, что они не выполнят импорт после начала завершения системы. Несоблюдение этого ограничения приведёт к случайным исключениям и авариям во время завершения работы интерпретатора (поскольку поздние попытки импорта попытаются получить доступ к механизму, который больше не находится в работоспособном состоянии).

© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/2.7/library/threading.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API