threading.md
1> **Источник:** https://python-all.ru/3.14/library/threading.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# `threading` – параллелизм на основе потоков89**Исходный код:** [Lib/threading.py](https://python-all.ru/src/3.14/Lib/threading.py)1011---1213Этот модуль предоставляет интерфейсы многопоточности более высокого уровня поверх низкоуровневого модуля [`_thread`](https://python-all.ru/3.14/library/_thread.html#module-_thread).1415[Доступность](https://python-all.ru/3.14/library/intro.html#availability): не WASI.1617Этот модуль не работает или недоступен на WebAssembly. Подробнее см. [платформы WebAssembly](https://python-all.ru/3.14/library/intro.html#wasm-availability).1819## Введение2021Модуль `threading` позволяет запускать несколько [потоков](https://python-all.ru/3.14/library/threading.html) (меньших единиц процесса) одновременно в рамках одного процесса. Он обеспечивает создание и управление потоками, позволяя выполнять задачи параллельно с разделением памяти. Потоки особенно полезны для задач, связанных с вводом-выводом, таких как файловые операции или сетевые запросы, где большая часть времени тратится на ожидание внешних ресурсов.2223Типичный вариант использования `threading` включает управление пулом рабочих потоков, которые могут параллельно обрабатывать несколько задач. Вот простой пример создания и запуска потоков с помощью [`Thread`](https://python-all.ru/3.14/library/threading.html#threading.Thread):2425```python26import threading27import time2829def crawl(link, delay=3):30 print(f"crawl started for {link}")31 time.sleep(delay) # Блокирующий ввод-вывод (имитация сетевого запроса)32 print(f"crawl ended for {link}")3334links = [35 "https://python.org",36 "https://docs.python.org",37 "https://peps.python.org",38]3940# Запустить потоки для каждой ссылки41threads = []42for link in links:43 # Использование `args` для передачи позиционных аргументов и `kwargs` для именованных аргументов44 t = threading.Thread(target=crawl, args=(link,), kwargs={"delay": 2})45 threads.append(t)4647# Запустить каждый поток48for t in threads:49 t.start()5051# Дождаться завершения всех потоков52for t in threads:53 t.join()54```5556Изменено в версии 3.7: Ранее этот модуль был опциональным, теперь он всегда доступен.5758> **См. также**59>60> [`concurrent.futures.ThreadPoolExecutor`](https://python-all.ru/3.14/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor) предлагает интерфейс более высокого уровня для отправки задач в фоновый поток без блокировки выполнения вызывающего потока, при этом позволяя получать их результаты по мере необходимости.61>62> [`queue`](https://python-all.ru/3.14/library/queue.html#module-queue) предоставляет потокобезопасный интерфейс для обмена данными между запущенными потоками.63>64> [`asyncio`](https://python-all.ru/3.14/library/asyncio.html#module-asyncio) предлагает альтернативный подход к достижению параллелизма на уровне задач без необходимости использования нескольких системных потоков.6566> **Примечание**67>68> В серии Python 2.x этот модуль содержал имена в стиле `camelCase` для некоторых методов и функций. Они объявлены устаревшими с Python 3.10, но всё ещё поддерживаются для совместимости с Python 2.5 и ниже.6970**Особенность реализации CPython:** В CPython из-за [глобальной блокировки интерпретатора](https://python-all.ru/3.14/glossary.html#term-global-interpreter-lock) только один поток может выполнять код Python одновременно (хотя некоторые библиотеки, ориентированные на производительность, могут обойти это ограничение). Если вы хотите, чтобы ваше приложение лучше использовало вычислительные ресурсы многоядерных машин, рекомендуется использовать [`multiprocessing`](https://python-all.ru/3.14/library/multiprocessing.html#module-multiprocessing) или [`concurrent.futures.ProcessPoolExecutor`](https://python-all.ru/3.14/library/concurrent.futures.html#concurrent.futures.ProcessPoolExecutor). Однако многопоточность всё ещё является подходящей моделью, если нужно запустить несколько задач с интенсивным вводом-выводом одновременно.7172## GIL и вопросы производительности7374В отличие от модуля [`multiprocessing`](https://python-all.ru/3.14/library/multiprocessing.html#module-multiprocessing), который использует отдельные процессы для обхода [глобальной блокировки интерпретатора](https://python-all.ru/3.14/glossary.html#term-global-interpreter-lock) (GIL), модуль threading работает в рамках одного процесса, что означает, что все потоки разделяют одно и то же адресное пространство. Однако GIL ограничивает прирост производительности многопоточности при выполнении задач, нагружающих процессор, поскольку одновременно только один поток может выполнять байт-код Python. Несмотря на это, потоки остаются полезным инструментом для достижения параллелизма во многих сценариях.7576Начиная с Python 3.13 сборки [со свободной многопоточностью](https://python-all.ru/3.14/glossary.html#term-free-threading) могут отключать GIL, обеспечивая истинно параллельное выполнение потоков, но эта функция не включена по умолчанию (см. [**PEP 703**](https://python-all.ru/3.14/library/threading.html)).7778## Ссылка7980Этот модуль определяет следующие функции:8182#### `threading.active_count()`8384Возвращает количество [`Thread`](https://python-all.ru/3.14/library/threading.html#threading.Thread) объектов, которые сейчас активны. Возвращённое число равно длине списка, возвращаемого [`enumerate()`](https://python-all.ru/3.14/library/threading.html#threading.enumerate).8586Функция `activeCount` является устаревшим псевдонимом для этой функции.8788#### `threading.current_thread()`8990Возвращает текущий [`Thread`](https://python-all.ru/3.14/library/threading.html#threading.Thread) объект, соответствующий потоку управления вызывающего кода. Если поток управления вызывающего кода не был создан через модуль `threading`, возвращается фиктивный объект потока с ограниченной функциональностью.9192Функция `currentThread` является устаревшим псевдонимом для этой функции.9394#### `threading.excepthook(args, /)`9596Обрабатывает необработанное исключение, вызванное [`Thread.run()`](https://python-all.ru/3.14/library/threading.html#threading.Thread.run).9798Аргумент *args* имеет следующие атрибуты:99100- *exc\_type*: тип исключения.101- *exc\_value*: значение исключения, может быть `None`.102- *exc\_traceback*: трассировка исключения, может быть `None`.103- *поток*: поток, вызвавший исключение, может быть `None`.104105Если *exc\_type* равен [`SystemExit`](https://python-all.ru/3.14/library/exceptions.html#SystemExit), исключение молча игнорируется. В противном случае исключение выводится на [`sys.stderr`](https://python-all.ru/3.14/library/sys.html#sys.stderr).106107Если эта функция вызывает исключение, [`sys.excepthook()`](https://python-all.ru/3.14/library/sys.html#sys.excepthook) вызывается для его обработки.108109`threading.excepthook()` можно переопределить, чтобы контролировать обработку необработанных исключений, вызванных [`Thread.run()`](https://python-all.ru/3.14/library/threading.html#threading.Thread.run).110111Сохранение *exc\_value* с помощью пользовательского перехватчика может создать циклическую ссылку. Её следует явно очистить, чтобы разорвать цикл ссылок, когда исключение больше не нужно.112113Сохранение *поток* с помощью пользовательского перехватчика может восстановить его, если он ссылается на объект, который находится в процессе финализации. Избегайте сохранения *поток* после завершения работы пользовательского перехватчика, чтобы не восстанавливать объекты.114115> **См. также**116>117> [`sys.excepthook()`](https://python-all.ru/3.14/library/sys.html#sys.excepthook) обрабатывает необработанные исключения.118119Добавлено в версии 3.8.120121#### `threading.__excepthook__`122123Хранит исходное значение [`threading.excepthook()`](https://python-all.ru/3.14/library/threading.html#threading.excepthook). Оно сохраняется, чтобы исходное значение можно было восстановить, если его вдруг заменят на сломанные или альтернативные объекты.124125Добавлено в версии 3.10.126127#### `threading.get_ident()`128129Возвращает «идентификатор потока» текущего потока. Это ненулевое целое число. Его значение не имеет прямого смысла; оно предназначено как уникальная метка, используемая, например, для индексации словаря с данными, специфичными для потока. Идентификаторы потоков могут быть переиспользованы, когда один поток завершается, а другой создаётся.130131Добавлено в версии 3.3.132133#### `threading.get_native_id()`134135Возвращает нативный целочисленный идентификатор потока, назначенный ядром для текущего потока. Это неотрицательное целое число. Его значение может использоваться для уникальной идентификации данного потока в системе (пока поток не завершится, после чего значение может быть повторно использовано ОС).136137[Доступность](https://python-all.ru/3.14/library/intro.html#availability): Windows, FreeBSD, Linux, macOS, OpenBSD, NetBSD, AIX, DragonFlyBSD, GNU/kFreeBSD.138139Добавлено в версии 3.8.140141Изменено в версии 3.13: Добавлена поддержка GNU/kFreeBSD.142143#### `threading.enumerate()`144145Возвращает список всех активных в данный момент объектов [`Thread`](https://python-all.ru/3.14/library/threading.html#threading.Thread). Список включает потоки-демоны и фиктивные объекты потоков, созданные [`current_thread()`](https://python-all.ru/3.14/library/threading.html#threading.current_thread). В него не входят завершённые потоки и потоки, которые ещё не были запущены. Однако главный поток всегда присутствует в результате, даже если он завершён.146147#### `threading.main_thread()`148149Возвращает основной объект [`Thread`](https://python-all.ru/3.14/library/threading.html#threading.Thread). В обычных условиях главный поток – это поток, с которого был запущен интерпретатор Python.150151Добавлено в версии 3.4.152153#### `threading.settrace(func)`154155Устанавливает трассировочную функцию для всех потоков, запущенных из модуля `threading`. Функция *func* будет передана в [`sys.settrace()`](https://python-all.ru/3.14/library/sys.html#sys.settrace) для каждого потока перед вызовом его метода [`run()`](https://python-all.ru/3.14/library/threading.html#threading.Thread.run).156157#### `threading.settrace_all_threads(func)`158159Устанавливает трассировочную функцию для всех потоков, запущенных из модуля `threading`, и всех потоков Python, которые выполняются в данный момент.160161Функция *func* будет передана в [`sys.settrace()`](https://python-all.ru/3.14/library/sys.html#sys.settrace) для каждого потока перед вызовом его метода [`run()`](https://python-all.ru/3.14/library/threading.html#threading.Thread.run).162163Добавлено в версии 3.12.164165#### `threading.gettrace()`166167Возвращает трассировочную функцию, установленную с помощью [`settrace()`](https://python-all.ru/3.14/library/threading.html#threading.settrace).168169Добавлено в версии 3.10.170171#### `threading.setprofile(func)`172173Устанавливает профилирующую функцию для всех потоков, запущенных из модуля `threading`. Функция *func* будет передана в [`sys.setprofile()`](https://python-all.ru/3.14/library/sys.html#sys.setprofile) для каждого потока перед вызовом его метода [`run()`](https://python-all.ru/3.14/library/threading.html#threading.Thread.run).174175#### `threading.setprofile_all_threads(func)`176177Устанавливает профилирующую функцию для всех потоков, запущенных из модуля `threading`, и всех потоков Python, которые выполняются в данный момент.178179Функция *func* будет передана в [`sys.setprofile()`](https://python-all.ru/3.14/library/sys.html#sys.setprofile) для каждого потока перед вызовом его метода [`run()`](https://python-all.ru/3.14/library/threading.html#threading.Thread.run).180181Добавлено в версии 3.12.182183#### `threading.getprofile()`184185Возвращает профилирующую функцию, установленную с помощью [`setprofile()`](https://python-all.ru/3.14/library/threading.html#threading.setprofile).186187Добавлено в версии 3.10.188189#### `threading.stack_size([size])`190191Возвращает размер стека потока, используемый при создании новых потоков. Необязательный аргумент *size* задаёт размер стека для впоследствии создаваемых потоков и должен быть равен 0 (используется платформенное или настроенное значение по умолчанию) или положительному целому числу не менее 32 768 (32 КиБ). Если *size* не указан, используется 0. Если изменение размера стека не поддерживается, возбуждается [`RuntimeError`](https://python-all.ru/3.14/library/exceptions.html#RuntimeError). Если указанный размер стека некорректен, возбуждается [`ValueError`](https://python-all.ru/3.14/library/exceptions.html#ValueError), а размер стека остаётся без изменений. 32 КиБ – это минимально поддерживаемый размер стека, достаточный для самого интерпретатора. Имейте в виду, что на некоторых платформах могут быть особые ограничения на значения размера стека, например, требование минимального размера больше 32 КиБ или выделения памяти кратно размеру системной страницы памяти – за более подробной информацией следует обращаться к документации платформы (обычно используются страницы по 4 КиБ; при отсутствии более точных сведений рекомендуется задавать размер стека кратно 4096).192193[Доступность](https://python-all.ru/3.14/library/intro.html#availability): Windows, pthreads.194195Unix-платформы с поддержкой потоков POSIX.196197Этот модуль также определяет следующую константу:198199#### `threading.TIMEOUT_MAX`200201Максимально допустимое значение для параметра *timeout* блокирующих функций ([`Lock.acquire()`](https://python-all.ru/3.14/library/threading.html#threading.Lock.acquire), [`RLock.acquire()`](https://python-all.ru/3.14/library/threading.html#threading.RLock.acquire), [`Condition.wait()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.wait) и т.д.). Указание тайм-аута, превышающего это значение, вызовет исключение [`OverflowError`](https://python-all.ru/3.14/library/exceptions.html#OverflowError).202203Добавлено в версии 3.2.204205Этот модуль определяет ряд классов, которые подробно описаны в разделах ниже.206207Дизайн этого модуля основан на модели потоков Java, хотя и нестрого. Однако если в Java блокировки и условные переменные являются базовым поведением каждого объекта, то в Python это отдельные объекты. Класс [`Thread`](https://python-all.ru/3.14/library/threading.html#threading.Thread) в Python поддерживает подмножество поведения класса Thread из Java; в настоящее время отсутствуют приоритеты, группы потоков, а потоки нельзя уничтожать, останавливать, приостанавливать, возобновлять или прерывать. Статические методы класса Thread из Java, если они реализованы, отображаются на функции уровня модуля.208209Все описанные ниже методы выполняются атомарно.210211### Данные, локальные для потока212213Данные, локальные для потока – это данные, значения которых привязаны к потоку. Если у вас есть данные, которые должны быть локальными для потока, создайте объект [`local`](https://python-all.ru/3.14/library/threading.html#threading.local) и используйте его атрибуты:214215```python216>>> mydata = local()217>>> mydata.number = 42218>>> mydata.number21942220```221222Также можно получить доступ к словарю объекта [`local`](https://python-all.ru/3.14/library/threading.html#threading.local):223224```python225>>> mydata.__dict__226{'number': 42}227>>> mydata.__dict__.setdefault('widgets', [])228[]229>>> mydata.widgets230[]231```232233Если обратиться к данным из другого потока:234235```python236>>> log = []237>>> def f():238... items = sorted(mydata.__dict__.items())239... log.append(items)240... mydata.number = 11241... log.append(mydata.number)242243>>> import threading244>>> thread = threading.Thread(target=f)245>>> thread.start()246>>> thread.join()247>>> log248[[], 11]249```250251мы получим другие данные. Более того, изменения, сделанные в другом потоке, не влияют на данные, видимые в этом потоке:252253```python254>>> mydata.number25542256```257258Разумеется, значения, получаемые из объекта [`local`](https://python-all.ru/3.14/library/threading.html#threading.local), включая их атрибут [`__dict__`](https://python-all.ru/3.14/reference/datamodel.html#object.__dict__), относятся к тому потоку, который был текущим на момент чтения атрибута. По этой причине обычно не следует сохранять эти значения между потоками, так как они применимы только к тому потоку, из которого получены.259260Можно создавать собственные объекты [`local`](https://python-all.ru/3.14/library/threading.html#threading.local), создавая подкласс класса `local`:261262```python263>>> class MyLocal(local):264... number = 2265... def __init__(self, /, **kw):266... self.__dict__.update(kw)267... def squared(self):268... return self.number ** 2269```270271Это может быть полезно для поддержки значений по умолчанию, методов и инициализации. Обратите внимание: если определить метод [`__init__()`](https://python-all.ru/3.14/reference/datamodel.html#object.__init__), он будет вызываться каждый раз, когда объект [`local`](https://python-all.ru/3.14/library/threading.html#threading.local) используется в отдельном потоке. Это необходимо для инициализации словаря каждого потока.272273Теперь, если создать объект [`local`](https://python-all.ru/3.14/library/threading.html#threading.local):274275```python276>>> mydata = MyLocal(color='red')277```278279мы получим число по умолчанию:280281```python282>>> mydata.number2832284```285286начальный цвет:287288```python289>>> mydata.color290'red'291>>> del mydata.color292```293294и метод, работающий с данными:295296```python297>>> mydata.squared()2984299```300301Как и раньше, можно обратиться к данным в отдельном потоке:302303```python304>>> log = []305>>> thread = threading.Thread(target=f)306>>> thread.start()307>>> thread.join()308>>> log309[[('color', 'red')], 11]310```311312не затрагивая данные этого потока:313314```python315>>> mydata.number3162317>>> mydata.color318Traceback (most recent call last):319...320AttributeError: 'MyLocal' object has no attribute 'color'321```322323Обратите внимание: подклассы могут определять [\_\_slots\_\_](https://python-all.ru/3.14/glossary.html#term-__slots__), но они не являются локальными для потока. Они разделяются между потоками:324325```python326>>> class MyLocal(local):327... __slots__ = 'number'328329>>> mydata = MyLocal()330>>> mydata.number = 42331>>> mydata.color = 'red'332```333334Итак, отдельный поток:335336```python337>>> thread = threading.Thread(target=f)338>>> thread.start()339>>> thread.join()340```341342влияет на то, что мы видим:343344```python345>>> mydata.number34611347```348349#### `class threading.local`350351Класс, представляющий данные, локальные для потока.352353### Объекты потоков354355Класс [`Thread`](https://python-all.ru/3.14/library/threading.html#threading.Thread) представляет собой активность, выполняемую в отдельном потоке управления. Есть два способа определить активность: передать вызываемый объект в конструктор или переопределить метод [`run()`](https://python-all.ru/3.14/library/threading.html#threading.Thread.run) в подклассе. Никакие другие методы (кроме конструктора) не должны переопределяться в подклассе. Иными словами, переопределяйте *только* методы `__init__()` и `run()` этого класса.356357После создания объекта потока его активность должна быть запущена вызовом метода [`start()`](https://python-all.ru/3.14/library/threading.html#threading.Thread.start) этого потока. Это вызывает метод [`run()`](https://python-all.ru/3.14/library/threading.html#threading.Thread.run) в отдельном потоке управления.358359После запуска активности поток считается «живым». Он перестаёт быть живым, когда завершается его метод [`run()`](https://python-all.ru/3.14/library/threading.html#threading.Thread.run) – либо нормально, либо из-за необработанного исключения. Метод [`is_alive()`](https://python-all.ru/3.14/library/threading.html#threading.Thread.is_alive) проверяет, жив ли поток.360361Другие потоки могут вызывать метод [`join()`](https://python-all.ru/3.14/library/threading.html#threading.Thread.join) потока. Это блокирует вызывающий поток до тех пор, пока поток, чей метод `join()` вызывается, не завершится.362363У потока есть имя. Имя можно передать конструктору, а также прочитать или изменить через атрибут [`name`](https://python-all.ru/3.14/library/threading.html#threading.Thread.name).364365Если метод [`run()`](https://python-all.ru/3.14/library/threading.html#threading.Thread.run) вызывает исключение, для его обработки вызывается [`threading.excepthook()`](https://python-all.ru/3.14/library/threading.html#threading.excepthook). По умолчанию `threading.excepthook()` молча игнорирует [`SystemExit`](https://python-all.ru/3.14/library/exceptions.html#SystemExit).366367Поток может быть помечен как «фоновый поток». Смысл этого флага в том, что вся программа Python завершается, когда остаются только фоновые потоки. Начальное значение наследуется от создающего потока. Флаг можно установить через свойство [`daemon`](https://python-all.ru/3.14/library/threading.html#threading.Thread.daemon) или аргумент конструктора *daemon*.368369> **Примечание**370>371> Фоновые потоки принудительно останавливаются при завершении программы. Их ресурсы (такие как открытые файлы, транзакции базы данных и т.п.) могут быть не освобождены должным образом. Если нужно, чтобы потоки завершались корректно, сделайте их не фоновыми и используйте подходящий механизм уведомлений, например [`Event`](https://python-all.ru/3.14/library/threading.html#threading.Event).372373Существует объект «главный поток»; он соответствует начальному потоку управления в программе Python. Это не фоновый поток.374375Существует возможность создания «фиктивных объектов потоков». Это объекты потоков, соответствующие «внешним потокам» – потокам управления, запущенным вне модуля threading, например напрямую из кода на C. Фиктивные объекты потоков имеют ограниченную функциональность; они всегда считаются живыми и фоновыми, и их нельзя [присоединить](https://python-all.ru/3.14/library/threading.html#meth-thread-join). Они никогда не удаляются, так как невозможно обнаружить завершение внешних потоков.376377#### `class threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None, context=None)`378379Этот конструктор всегда следует вызывать с именованными аргументами. Аргументы:380381*group* должно быть `None`, так как он зарезервирован для будущих расширений, когда будет реализован класс `ThreadGroup`.382383*target* – это вызываемый объект, который будет вызван методом [`run()`](https://python-all.ru/3.14/library/threading.html#threading.Thread.run). По умолчанию `None`, то есть ничего не вызывается.384385*name* – это имя потока. По умолчанию создаётся уникальное имя вида «Thread-*N*», где *N* – небольшое десятичное число, или «Thread-*N* (target)», где «target» – это `target.__name__`, если указан аргумент *target*.386387*args* – это список или кортеж аргументов для вызова target. По умолчанию `()`.388389*kwargs* – это словарь именованных аргументов для вызова target. По умолчанию `{}`.390391Если не `None`, параметр *daemon* явно задаёт, является ли поток демоническим. Если `None` (по умолчанию), свойство демоничности наследуется от текущего потока.392393*context* – это значение [`Context`](https://python-all.ru/3.14/library/contextvars.html#contextvars.Context), используемое при запуске потока. Значение по умолчанию – `None`, что означает, что поведение управляется флагом [`sys.flags.thread_inherit_context`](https://python-all.ru/3.14/library/sys.html#sys.flags.thread_inherit_context). Если флаг истинен, потоки запускаются с копией контекста вызывающего [`start()`](https://python-all.ru/3.14/library/threading.html#threading.Thread.start). Если ложен – с пустым контекстом. Чтобы явно запустить с пустым контекстом, передайте новый экземпляр [`Context()`](https://python-all.ru/3.14/library/contextvars.html#contextvars.Context). Чтобы явно запустить с копией текущего контекста, передайте значение из [`copy_context()`](https://python-all.ru/3.14/library/contextvars.html#contextvars.copy_context). По умолчанию флаг равен true для сборок со свободной многопоточностью и false в остальных случаях.394395Если подкласс переопределяет конструктор, он должен обязательно вызвать конструктор базового класса (`Thread.__init__()`) перед любыми другими действиями с потоком.396397Изменено в версии 3.3: Добавлен параметр *daemon*.398399Изменено в версии 3.10: Используется имя *target*, если аргумент *name* опущен.400401Изменено в версии 3.14: Добавлен параметр *context*.402403#### `start()`404405Запускает выполнение потока.406407Этот метод должен вызываться не более одного раза для каждого объекта потока. Он обеспечивает вызов метода [`run()`](https://python-all.ru/3.14/library/threading.html#threading.Thread.run) объекта в отдельном потоке управления.408409Этот метод возбуждает исключение [`RuntimeError`](https://python-all.ru/3.14/library/exceptions.html#RuntimeError), если вызван более одного раза для одного и того же объекта потока.410411Если поддерживается, устанавливает имя потока операционной системы в [`threading.Thread.name`](https://python-all.ru/3.14/library/threading.html#threading.Thread.name). Имя может быть усечено в зависимости от ограничений операционной системы на длину имени потока.412413Изменено в версии 3.14: Устанавливает имя потока операционной системы.414415#### `run()`416417Метод, представляющий действие потока.418419Этот метод можно переопределить в подклассе. Стандартный метод `run()` вызывает вызываемый объект, переданный конструктору объекта в качестве аргумента *target* (если он задан), с позиционными и именованными аргументами, взятыми соответственно из аргументов *args* и *kwargs*.420421Использование списка или кортежа в качестве аргумента *args*, переданного методу `Thread`, может дать тот же эффект.422423Пример:424425```python426>>> from threading import Thread427>>> t = Thread(target=print, args=[1])428>>> t.run()4291430>>> t = Thread(target=print, args=(1,))431>>> t.run()4321433```434435#### `join(timeout=None)`436437Ожидает завершения потока. Блокирует вызывающий поток до тех пор, пока поток, у которого вызван метод `join()`, не завершится – либо нормально, либо из-за необработанного исключения – или пока не истечёт заданный тайм-аут.438439Если аргумент *timeout* присутствует и не равен `None`, он должен быть числом с плавающей точкой, задающим тайм-аут операции в секундах (или его долях). Поскольку `join()` всегда возвращает `None`, необходимо вызвать [`is_alive()`](https://python-all.ru/3.14/library/threading.html#threading.Thread.is_alive) после `join()`, чтобы определить, произошёл ли тайм-аут – если поток ещё жив, вызов `join()` превысил тайм-аут.440441Если аргумент *timeout* отсутствует или равен `None`, операция блокируется до завершения потока.442443Поток можно присоединить много раз.444445`join()` возбуждает [`RuntimeError`](https://python-all.ru/3.14/library/exceptions.html#RuntimeError), если предпринимается попытка присоединиться к текущему потоку, так как это привело бы к взаимоблокировке. Также ошибочно `join()` поток до его запуска, и попытки сделать это возбуждают то же исключение.446447Если предпринимается попытка присоединиться к выполняющемуся демоническому потоку на поздних этапах [завершения работы Python](https://python-all.ru/3.14/glossary.html#term-interpreter-shutdown), `join()` возбуждает исключение [`PythonFinalizationError`](https://python-all.ru/3.14/library/exceptions.html#PythonFinalizationError).448449Изменено в версии 3.14: Может возбуждать [`PythonFinalizationError`](https://python-all.ru/3.14/library/exceptions.html#PythonFinalizationError).450451#### `name`452453Строка, используемая только для идентификации. Она не имеет семантического значения. Разным потокам можно задать одно и то же имя. Начальное имя устанавливается конструктором.454455На некоторых платформах имя потока устанавливается на уровне операционной системы при запуске потока, чтобы оно отображалось в диспетчерах задач. Это имя может быть усечено для соответствия системному ограничению (например, 15 байт в Linux или 63 байта в macOS).456457Изменения *name* отражаются на уровне ОС только при переименовании текущего выполняющегося потока. (Установка атрибута *name* другого потока обновляет только объект Thread в Python.)458459#### `getName()`460461#### `setName()`462463Устаревший API геттера/сеттера для [`name`](https://python-all.ru/3.14/library/threading.html#threading.Thread.name); используйте его напрямую как свойство.464465Устарело с версии 3.10.466467#### `ident`468469«Идентификатор потока» этого потока или `None`, если поток не был запущен. Это ненулевое целое число. См. функцию [`get_ident()`](https://python-all.ru/3.14/library/threading.html#threading.get_ident). Идентификаторы потоков могут быть повторно использованы, когда поток завершается и создаётся другой поток. Идентификатор доступен даже после завершения потока.470471#### `native_id`472473Идентификатор потока (`TID`), назначенный ОС (ядром). Это неотрицательное целое число или `None`, если поток не был запущен. См. функцию [`get_native_id()`](https://python-all.ru/3.14/library/threading.html#threading.get_native_id). Это значение может использоваться для уникальной идентификации данного потока в масштабе системы (до завершения потока, после чего значение может быть повторно использовано ОС).474475> **Примечание**476>477> Подобно идентификаторам процессов, идентификаторы потоков действительны (гарантированно уникальны в масштабе системы) только с момента создания потока до его завершения.478479[Доступность](https://python-all.ru/3.14/library/intro.html#availability): Windows, FreeBSD, Linux, macOS, OpenBSD, NetBSD, AIX, DragonFlyBSD.480481Добавлено в версии 3.8.482483#### `is_alive()`484485Возвращает, жив ли поток.486487Этот метод возвращает `True` непосредственно перед началом выполнения метода [`run()`](https://python-all.ru/3.14/library/threading.html#threading.Thread.run) и до завершения метода `run()`. Функция модуля [`enumerate()`](https://python-all.ru/3.14/library/threading.html#threading.enumerate) возвращает список всех живых потоков.488489#### `daemon`490491Логическое значение, указывающее, является ли этот поток демоном (`True`) или нет (`False`). Это должно быть установлено до вызова [`start()`](https://python-all.ru/3.14/library/threading.html#threading.Thread.start), иначе будет возбуждено [`RuntimeError`](https://python-all.ru/3.14/library/exceptions.html#RuntimeError). Его начальное значение наследуется от создающего потока; главный поток не является потоком-демоном, поэтому все потоки, созданные в главном потоке, по умолчанию имеют `daemon` = `False`.492493Вся программа Python завершается, когда не остаётся ни одного живого потока, не являющегося демоном.494495#### `isDaemon()`496497#### `setDaemon()`498499Устаревший API геттера/сеттера для [`daemon`](https://python-all.ru/3.14/library/threading.html#threading.Thread.daemon); используйте его напрямую как свойство.500501Устарело с версии 3.10.502503### Объекты блокировки504505Примитивная блокировка – это примитив синхронизации, который при захвате не принадлежит какому-либо определённому потоку. В Python в настоящее время это самый низкоуровневый доступный примитив синхронизации, реализованный непосредственно в расширении модуля [`_thread`](https://python-all.ru/3.14/library/_thread.html#module-_thread).506507Примитивная блокировка может находиться в одном из двух состояний: «захвачена» или «свободна». Она создаётся в свободном состоянии. У неё есть два основных метода: [`acquire()`](https://python-all.ru/3.14/library/threading.html#threading.Lock.acquire) и [`release()`](https://python-all.ru/3.14/library/threading.html#threading.Lock.release). Когда состояние свободно, вызов `acquire()` переводит его в захваченное и немедленно возвращается. Когда состояние захвачено, `acquire()` блокируется до тех пор, пока вызов `release()` в другом потоке не переведёт его в свободное; затем вызов `acquire()` снова устанавливает захваченное состояние и возвращается. Метод `release()` следует вызывать только в захваченном состоянии; он переводит состояние в свободное и немедленно возвращается. При попытке освободить свободную блокировку будет возбуждено [`RuntimeError`](https://python-all.ru/3.14/library/exceptions.html#RuntimeError).508509Блокировки также поддерживают [протокол контекстного менеджера](https://python-all.ru/3.14/library/threading.html#with-locks).510511Когда несколько потоков заблокированы в [`acquire()`](https://python-all.ru/3.14/library/threading.html#threading.Lock.acquire) в ожидании перехода состояния в свободное, только один поток продолжает выполнение, когда вызов [`release()`](https://python-all.ru/3.14/library/threading.html#threading.Lock.release) переводит состояние в свободное; какой именно из ожидающих потоков продолжит, не определено и может различаться в разных реализациях.512513Все методы выполняются атомарно.514515#### `class threading.Lock`516517Класс, реализующий объекты примитивной блокировки. Как только поток захватил блокировку, последующие попытки захватить её блокируются до тех пор, пока она не будет освобождена; любой поток может освободить её.518519Изменено в версии 3.13: `Lock` теперь является классом. В более ранних версиях Python `Lock` была фабричной функцией, которая возвращала экземпляр внутреннего закрытого типа блокировки.520521#### `acquire(blocking=True, timeout=-1)`522523Захватывает блокировку, блокирующую или неблокирующую.524525При вызове с аргументом *blocking*, установленным в `True` (по умолчанию), блокируется до тех пор, пока блокировка не станет свободной, затем устанавливает её в захваченное состояние и возвращает `True`.526527При вызове с аргументом *blocking*, установленным в `False`, не блокируется. Если вызов с *blocking*, установленным в `True`, должен был бы заблокироваться, немедленно возвращает `False`; в противном случае устанавливает блокировку в захваченное состояние и возвращает `True`.528529При вызове с аргументом *timeout* с плавающей запятой, установленным в положительное значение, блокируется на время, не превышающее количество секунд, указанное в *timeout*, и до тех пор, пока блокировка не может быть захвачена. Аргумент *timeout*, равный `-1`, означает неограниченное ожидание. Запрещается указывать *timeout*, когда *blocking* равно `False`.530531Возвращаемое значение равно `True`, если блокировка успешно захвачена, и `False` в противном случае (например, если *timeout* истёк).532533Изменено в версии 3.2: Параметр *timeout* является новым.534535Изменено в версии 3.2: Теперь захват блокировки может быть прерван сигналами в POSIX, если базовая реализация потоков это поддерживает.536537Изменено в версии 3.14: Теперь захват блокировки может быть прерван сигналами в Windows.538539#### `release()`540541Освобождает блокировку. Может вызываться из любого потока, а не только из того, который захватил блокировку.542543Когда блокировка установлена, сбрасывает её в снятое состояние и возвращает управление. Если другие потоки заблокированы в ожидании освобождения блокировки, ровно одному из них разрешается продолжить работу.544545При вызове на не заблокированной блокировке возбуждается исключение [`RuntimeError`](https://python-all.ru/3.14/library/exceptions.html#RuntimeError).546547Возвращаемое значение отсутствует.548549#### `locked()`550551Возвращает `True`, если блокировка захвачена.552553### Объекты RLock554555Повторно входимая блокировка – это примитив синхронизации, который может быть захвачен одним и тем же потоком несколько раз. Внутри она использует понятия «поток-владелец» и «уровень рекурсии» в дополнение к состоянию «заблокировано/разблокировано», используемому простыми блокировками. В заблокированном состоянии блокировкой владеет какой-то поток; в разблокированном состоянии ею не владеет ни один поток.556557Потоки вызывают метод [`acquire()`](https://python-all.ru/3.14/library/threading.html#threading.RLock.acquire) блокировки, чтобы заблокировать её, и метод [`release()`](https://python-all.ru/3.14/library/threading.html#threading.Lock.release), чтобы разблокировать.558559> **Примечание**560>561> Повторно входимые блокировки поддерживают [протокол управления контекстом](https://python-all.ru/3.14/library/threading.html#with-locks), поэтому рекомендуется использовать [`with`](https://python-all.ru/3.14/reference/compound_stmts.html#with) вместо ручного вызова [`acquire()`](https://python-all.ru/3.14/library/threading.html#threading.RLock.acquire) и [`release()`](https://python-all.ru/3.14/library/threading.html#threading.RLock.release) для захвата и освобождения блокировки в блоке кода.562563Пары вызовов [`acquire()`](https://python-all.ru/3.14/library/threading.html#threading.RLock.acquire)/[`release()`](https://python-all.ru/3.14/library/threading.html#threading.RLock.release) у RLock могут быть вложенными, в отличие от [`acquire()`](https://python-all.ru/3.14/library/threading.html#threading.Lock.acquire)/[`release()`](https://python-all.ru/3.14/library/threading.html#threading.Lock.release) у Lock. Только последний `release()` (`release()` самой внешней пары) сбрасывает блокировку в разблокированное состояние и позволяет другому потоку, заблокированному в `acquire()`, продолжить работу.564565[`acquire()`](https://python-all.ru/3.14/library/threading.html#threading.RLock.acquire)/[`release()`](https://python-all.ru/3.14/library/threading.html#threading.RLock.release) должны использоваться парами: каждый вызов acquire должен сопровождаться release в том же потоке, который захватил блокировку. Если не вызвать release столько же раз, сколько была захвачена блокировка, это может привести к взаимоблокировке.566567#### `class threading.RLock`568569Этот класс реализует объекты повторно входимой блокировки. Повторно входимая блокировка должна быть освобождена тем же потоком, который её захватил. После того как поток захватил повторно входимую блокировку, этот же поток может захватить её снова без блокировки; при этом поток должен освободить её один раз за каждый захват.570571Обратите внимание, что `RLock` на самом деле является фабричной функцией, которая возвращает экземпляр наиболее эффективной версии конкретного класса RLock, поддерживаемой платформой.572573#### `acquire(blocking=True, timeout=-1)`574575Захватывает блокировку, блокирующую или неблокирующую.576577> **См. также**578>579> **[Использование RLock в качестве менеджера контекста](https://python-all.ru/3.14/library/threading.html#with-locks)**580>581> Рекомендуется вместо ручных вызовов `acquire()` и [`release()`](https://python-all.ru/3.14/library/threading.html#threading.RLock.release), когда это возможно.582583При вызове с аргументом *blocking*, установленным в `True` (по умолчанию):584585> - Если ни один поток не владеет блокировкой, захватить блокировку и немедленно вернуть управление.586> - Если другой поток владеет блокировкой, блокироваться до тех пор, пока не удастся захватить блокировку, или до истечения *timeout*, если он задан положительным числом с плавающей точкой.587> - Если тот же поток владеет блокировкой, захватить блокировку снова и немедленно вернуть управление. В этом различие между [`Lock`](https://python-all.ru/3.14/library/threading.html#threading.Lock) и `RLock`; `Lock` обрабатывает этот случай так же, как предыдущий, блокируясь до тех пор, пока блокировку не удастся захватить.588589При вызове с аргументом *blocking*, установленным в `False`:590591> - Если ни один поток не владеет блокировкой, захватить блокировку и немедленно вернуть управление.592> - Если другой поток владеет блокировкой, немедленно вернуть управление.593> - Если тот же поток владеет блокировкой, захватить блокировку снова и немедленно вернуть управление.594595Во всех случаях, если поток смог захватить блокировку, возвращает `True`. Если поток не смог захватить блокировку (например, если не ожидал или истекло время ожидания), возвращает `False`.596597При многократном вызове, если не вызвать [`release()`](https://python-all.ru/3.14/library/threading.html#threading.RLock.release) столько же раз, это может привести к взаимоблокировке. Рекомендуется использовать `RLock` в качестве менеджера контекста, а не вызывать acquire/release напрямую.598599Изменено в версии 3.2: Параметр *timeout* является новым.600601#### `release()`602603Освобождает блокировку, уменьшая уровень рекурсии. Если после уменьшения он становится нулевым, сбрасывает блокировку в разблокированное состояние (не принадлежит ни одному потоку), и, если другие потоки заблокированы в ожидании освобождения блокировки, ровно одному из них разрешается продолжить. Если после уменьшения уровень рекурсии всё ещё ненулевой, блокировка остаётся заблокированной и принадлежит вызывающему потоку.604605Вызывайте этот метод только в том случае, если вызывающий поток владеет блокировкой. Если этот метод вызывается, когда блокировка не захвачена, возбуждается [`RuntimeError`](https://python-all.ru/3.14/library/exceptions.html#RuntimeError).606607Возвращаемое значение отсутствует.608609#### `locked()`610611Возвращает булево значение, указывающее, заблокирован ли данный объект в данный момент.612613Добавлено в версии 3.14.614615### Объекты Condition616617Переменная условия всегда связана с какой-либо блокировкой; её можно передать, или же она будет создана по умолчанию. Передача блокировки полезна, когда несколько переменных условия должны совместно использовать одну и ту же блокировку. Блокировка является частью объекта условия: не нужно отслеживать её отдельно.618619Переменная условия подчиняется [протоколу менеджера контекста](https://python-all.ru/3.14/library/threading.html#with-locks): использование выражения `with` захватывает связанную блокировку на время выполнения вложенного блока. Методы [`acquire()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.acquire) и [`release()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.release) также вызывают соответствующие методы связанной блокировки.620621Остальные методы должны вызываться, когда связанная блокировка удерживается. Метод [`wait()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.wait) освобождает блокировку, а затем блокируется, пока другой поток не пробудит его вызовом [`notify()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.notify) или [`notify_all()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.notify_all). После пробуждения метод `wait()` повторно захватывает блокировку и возвращает управление. Также можно указать тайм-аут.622623Метод [`notify()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.notify) пробуждает один из потоков, ожидающих переменную условия, если таковые имеются. Метод [`notify_all()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.notify_all) пробуждает все потоки, ожидающие переменную условия.624625Примечание: методы [`notify()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.notify) и [`notify_all()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.notify_all) не освобождают блокировку; это означает, что пробуждённый поток (или потоки) не вернутся из своего вызова [`wait()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.wait) немедленно, а только когда поток, вызвавший `notify()` или `notify_all()`, наконец откажется от владения блокировкой.626627Типичный стиль программирования с использованием переменных условия использует блокировку для синхронизации доступа к некоторому общему состоянию; потоки, заинтересованные в определённом изменении состояния, многократно вызывают [`wait()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.wait), пока не увидят желаемое состояние, в то время как потоки, изменяющие состояние, вызывают [`notify()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.notify) или [`notify_all()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.notify_all), когда они изменяют состояние таким образом, что это может быть желаемым состоянием для одного из ожидающих. Например, следующий код представляет собой общую ситуацию «производитель-потребитель» с неограниченной ёмкостью буфера:628629```python630# Потребить один элемент631with cv:632 while not an_item_is_available():633 cv.wait()634 get_an_available_item()635636# Произвести один элемент637with cv:638 make_an_item_available()639 cv.notify()640```641642Цикл `while`, проверяющий условие приложения, необходим, потому что [`wait()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.wait) может вернуться после произвольно долгого времени, и условие, которое вызвало вызов [`notify()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.notify), может больше не выполняться. Это присуще многопоточному программированию. Метод [`wait_for()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.wait_for) можно использовать для автоматизации проверки условия и упрощения расчёта тайм-аутов:643644```python645# Потребить элемент646with cv:647 cv.wait_for(an_item_is_available)648 get_an_available_item()649```650651Чтобы выбрать между [`notify()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.notify) и [`notify_all()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.notify_all), подумайте, может ли одно изменение состояния быть интересным только одному или нескольким ожидающим потокам. Например, в типичной ситуации «производитель-потребитель» добавление одного элемента в буфер требует пробуждения только одного потока-потребителя.652653#### `class threading.Condition(lock=None)`654655Этот класс реализует объекты переменной условия. Переменная условия позволяет одному или нескольким потокам ожидать, пока другой поток не уведомит их.656657Если аргумент *lock* передан и не равен `None`, он должен быть объектом [`Lock`](https://python-all.ru/3.14/library/threading.html#threading.Lock) или [`RLock`](https://python-all.ru/3.14/library/threading.html#threading.RLock) и используется в качестве базовой блокировки. В противном случае создаётся новый объект `RLock`, который используется в качестве базовой блокировки.658659Изменено в версии 3.3: изменён с фабричной функции на класс.660661#### `acquire(*args)`662663Захватывает базовую блокировку. Этот метод вызывает соответствующий метод базовой блокировки; возвращаемое значение – то, что возвращает этот метод.664665#### `release()`666667Освобождает базовую блокировку. Этот метод вызывает соответствующий метод базовой блокировки; возвращаемое значение отсутствует.668669#### `locked()`670671Возвращает булево значение, указывающее, заблокирован ли данный объект в данный момент.672673Добавлено в версии 3.14.674675#### `wait(timeout=None)`676677Ожидает до получения уведомления или до наступления тайм-аута. Если вызывающий поток не захватил блокировку при вызове этого метода, возбуждается [`RuntimeError`](https://python-all.ru/3.14/library/exceptions.html#RuntimeError).678679Этот метод освобождает базовую блокировку, а затем блокируется до тех пор, пока не будет пробуждён вызовом [`notify()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.notify) или [`notify_all()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.notify_all) для той же переменной условия в другом потоке, или пока не наступит необязательный тайм-аут. После пробуждения или истечения тайм-аута он повторно захватывает блокировку и возвращает управление.680681Если аргумент *timeout* присутствует и не равен `None`, он должен быть числом с плавающей точкой, задающим тайм-аут для операции в секундах (или долях секунды).682683Если базовая блокировка является [`RLock`](https://python-all.ru/3.14/library/threading.html#threading.RLock), она не освобождается с помощью метода [`release()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.release), поскольку это может не разблокировать блокировку, если она была захвачена несколько раз рекурсивно. Вместо этого используется внутренний интерфейс класса `RLock`, который действительно разблокирует её, даже если она была рекурсивно захвачена несколько раз. Затем используется другой внутренний интерфейс для восстановления уровня рекурсии при повторном захвате блокировки.684685Возвращаемое значение равно `True`, если только заданный *timeout* не истёк; в этом случае оно равно `False`.686687Изменено в версии 3.2: Ранее метод всегда возвращал `None`.688689#### `wait_for(predicate, timeout=None)`690691Ожидает, пока условие не станет истинным. *predicate* должен быть вызываемым объектом, результат которого будет интерпретироваться как булево значение. Можно указать *timeout*, задающий максимальное время ожидания.692693Этот вспомогательный метод может многократно вызывать [`wait()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.wait) до тех пор, пока предикат не будет удовлетворён или пока не наступит тайм-аут. Возвращаемое значение – последнее возвращаемое значение предиката; оно будет равно `False`, если время ожидания истекло.694695Если не учитывать возможность тайм-аута, вызов этого метода примерно эквивалентен следующему коду:696697```python698while not predicate():699 cv.wait()700```701702Следовательно, применяются те же правила, что и для [`wait()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.wait): блокировка должна быть захвачена при вызове и повторно захватывается при возврате. Предикат вычисляется при удерживаемой блокировке.703704Добавлено в версии 3.2.705706#### `notify(n=1)`707708По умолчанию пробуждает один поток, ожидающий на этом условии, если таковой имеется. Если вызывающий поток не захватил блокировку на момент вызова этого метода, возникает [`RuntimeError`](https://python-all.ru/3.14/library/exceptions.html#RuntimeError).709710Этот метод пробуждает не более *n* потоков, ожидающих на переменной условия; если ни один поток не ожидает, он ничего не делает.711712Текущая реализация пробуждает ровно *n* потоков, если ожидает не менее *n* потоков. Однако полагаться на такое поведение небезопасно. В будущем оптимизированная реализация может иногда пробуждать более *n* потоков.713714Примечание: пробуждённый поток на самом деле не возвращается из вызова [`wait()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.wait), пока не сможет повторно захватить блокировку. Поскольку `notify()` не освобождает блокировку, это должен сделать его вызывающий код.715716#### `notify_all()`717718Пробуждает все потоки, ожидающие на этом условии. Этот метод действует как [`notify()`](https://python-all.ru/3.14/library/threading.html#threading.Condition.notify), но пробуждает все ожидающие потоки вместо одного. Если вызывающий поток не захватил блокировку на момент вызова этого метода, возникает [`RuntimeError`](https://python-all.ru/3.14/library/exceptions.html#RuntimeError).719720Метод `notifyAll` – устаревший псевдоним для этого метода.721722### Объекты семафоров723724Это один из старейших примитивов синхронизации в истории компьютерных наук, изобретённый ранним нидерландским учёным Эдсгером В. Дейкстрой (он использовал имена `P()` и `V()` вместо [`acquire()`](https://python-all.ru/3.14/library/threading.html#threading.Semaphore.acquire) и [`release()`](https://python-all.ru/3.14/library/threading.html#threading.Semaphore.release)).725726Семафор управляет внутренним счётчиком, который уменьшается при каждом вызове [`acquire()`](https://python-all.ru/3.14/library/threading.html#threading.Semaphore.acquire) и увеличивается при каждом вызове [`release()`](https://python-all.ru/3.14/library/threading.html#threading.Semaphore.release). Счётчик никогда не может стать меньше нуля; когда `acquire()` обнаруживает, что он равен нулю, он блокируется, ожидая, пока другой поток вызовет `release()`.727728Семафоры также поддерживают [протокол менеджера контекста](https://python-all.ru/3.14/library/threading.html#with-locks).729730#### `class threading.Semaphore(value=1)`731732Этот класс реализует объекты семафоров. Семафор управляет атомарным счётчиком, представляющим количество вызовов [`release()`](https://python-all.ru/3.14/library/threading.html#threading.Semaphore.release) минус количество вызовов [`acquire()`](https://python-all.ru/3.14/library/threading.html#threading.Semaphore.acquire) плюс начальное значение. Метод `acquire()` при необходимости блокируется, пока не сможет вернуться, не сделав счётчик отрицательным. Если не указано, *value* по умолчанию равно 1.733734Необязательный аргумент задаёт начальное *value* для внутреннего счётчика; по умолчанию оно равно `1`. Если указанное *value* меньше 0, возникает [`ValueError`](https://python-all.ru/3.14/library/exceptions.html#ValueError).735736Изменено в версии 3.3: изменён с фабричной функции на класс.737738#### `acquire(blocking=True, timeout=None)`739740Захватывает семафор.741742При вызове без аргументов:743744- Если внутренний счётчик больше нуля при входе, уменьшить его на единицу и немедленно вернуть `True`.745- Если внутренний счётчик равен нулю при входе, блокироваться до пробуждения вызовом [`release()`](https://python-all.ru/3.14/library/threading.html#threading.Semaphore.release). После пробуждения (когда счётчик станет больше 0) уменьшить счётчик на 1 и вернуть `True`. Каждый вызов `release()` пробуждает ровно один поток. На порядок пробуждения потоков полагаться не следует.746747При вызове с *blocking*, установленным в `False`, не блокироваться. Если вызов без аргументов заблокировался бы, немедленно вернуть `False`; в противном случае сделать то же, что и при вызове без аргументов, и вернуть `True`.748749При вызове с *timeout*, отличным от `None`, он будет блокироваться не более *timeout* секунд. Если acquire не завершится успешно за это время, вернуть `False`. В противном случае вернуть `True`.750751Изменено в версии 3.2: Параметр *timeout* является новым.752753#### `release(n=1)`754755Освобождает семафор, увеличивая внутренний счётчик на *n*. Если на входе он был равен нулю, и другие потоки ожидают его увеличения, пробуждает *n* из этих потоков.756757Изменено в версии 3.9: Добавлен параметр *n* для освобождения нескольких ожидающих потоков одновременно.758759#### `class threading.BoundedSemaphore(value=1)`760761Класс, реализующий объекты ограниченного семафора. Ограниченный семафор проверяет, что его текущее значение не превышает начальное. Если превышает, возникает [`ValueError`](https://python-all.ru/3.14/library/exceptions.html#ValueError). В большинстве ситуаций семафоры используются для защиты ресурсов с ограниченной ёмкостью. Если семафор освобождается слишком много раз, это признак ошибки. Если не указано, *value* по умолчанию равно 1.762763Изменено в версии 3.3: изменён с фабричной функции на класс.764765### [`Semaphore`](https://python-all.ru/3.14/library/threading.html#threading.Semaphore) пример766767Семафоры часто используются для защиты ресурсов с ограниченной ёмкостью, например, сервера базы данных. В любой ситуации, когда размер ресурса фиксирован, следует использовать ограниченный семафор. Перед запуском рабочих потоков главный поток инициализирует семафор:768769```python770maxconnections = 5771# ...772pool_sema = BoundedSemaphore(value=maxconnections)773```774775После запуска рабочие потоки вызывают методы acquire и release семафора, когда им нужно подключиться к серверу:776777```python778with pool_sema:779 conn = connectdb()780 try:781 # ... использовать соединение ...782 finally:783 conn.close()784```785786Использование ограниченного семафора снижает вероятность того, что ошибка программирования, приводящая к освобождению семафора большее количество раз, чем его захват, останется незамеченной.787788### Объекты событий789790Это один из простейших механизмов взаимодействия между потоками: один поток сигнализирует о событии, а другие потоки ожидают его.791792Объект события управляет внутренним флагом, который можно установить в true с помощью метода [`set()`](https://python-all.ru/3.14/library/threading.html#threading.Event.set) и сбросить в false с помощью метода [`clear()`](https://python-all.ru/3.14/library/threading.html#threading.Event.clear). Метод [`wait()`](https://python-all.ru/3.14/library/threading.html#threading.Event.wait) блокируется до тех пор, пока флаг не станет true.793794#### `class threading.Event`795796Класс, реализующий объекты событий. Событие управляет флагом, который можно установить в true методом [`set()`](https://python-all.ru/3.14/library/threading.html#threading.Event.set) и сбросить в false методом [`clear()`](https://python-all.ru/3.14/library/threading.html#threading.Event.clear). Метод [`wait()`](https://python-all.ru/3.14/library/threading.html#threading.Event.wait) блокируется до тех пор, пока флаг не станет true. Изначально флаг равен false.797798Изменено в версии 3.3: изменён с фабричной функции на класс.799800#### `is_set()`801802Возвращает `True` тогда и только тогда, когда внутренний флаг равен true.803804Метод `isSet` – устаревший псевдоним для этого метода.805806#### `set()`807808Устанавливает внутренний флаг в true. Все потоки, ожидающие его установки, пробуждаются. Потоки, вызывающие [`wait()`](https://python-all.ru/3.14/library/threading.html#threading.Event.wait) после того, как флаг стал true, не будут блокироваться вовсе.809810#### `clear()`811812Сбрасывает внутренний флаг в false. После этого потоки, вызывающие [`wait()`](https://python-all.ru/3.14/library/threading.html#threading.Event.wait), будут блокироваться до тех пор, пока не будет вызван [`set()`](https://python-all.ru/3.14/library/threading.html#threading.Event.set), чтобы снова установить внутренний флаг в true.813814#### `wait(timeout=None)`815816Блокируется до тех пор, пока внутренний флаг равен false, и не истёк переданный тайм-аут (если он задан). Возвращаемое значение указывает причину, по которой этот блокирующий метод вернул управление: `True` – если возврат произошёл из-за установки внутреннего флага в true, или `False` – если был задан тайм-аут и внутренний флаг не стал true за указанное время ожидания.817818Если аргумент timeout присутствует и не равен `None`, он должен быть числом с плавающей запятой, задающим время ожидания операции в секундах (или долях секунды).819820Изменено в версии 3.1: Ранее метод всегда возвращал `None`.821822### Объекты таймеров823824Этот класс представляет действие, которое должно быть выполнено только по прошествии определённого времени – таймер. [`Timer`](https://python-all.ru/3.14/library/threading.html#threading.Timer) является подклассом [`Thread`](https://python-all.ru/3.14/library/threading.html#threading.Thread) и, таким образом, служит примером создания пользовательских потоков.825826Таймеры запускаются, как и потоки, вызовом метода [`Timer.start`](https://python-all.ru/3.14/library/threading.html#threading.Thread.start). Таймер можно остановить (до начала его действия) вызовом метода [`cancel()`](https://python-all.ru/3.14/library/threading.html#threading.Timer.cancel). Интервал, который таймер будет ждать перед выполнением действия, может не совпадать в точности с интервалом, указанным пользователем.827828Например:829830```python831def hello():832 print("hello, world")833834t = Timer(30.0, hello)835t.start() # через 30 секунд будет выведено "hello, world"836```837838#### `class threading.Timer(interval, function, args=None, kwargs=None)`839840Создаёт таймер, который запустит *function* с аргументами *args* и именованными аргументами *kwargs* по прошествии *interval* секунд. Если *args* равен `None` (значение по умолчанию), будет использован пустой список. Если *kwargs* равен `None` (значение по умолчанию), будет использован пустой словарь.841842Изменено в версии 3.3: изменён с фабричной функции на класс.843844#### `cancel()`845846Останавливает таймер и отменяет выполнение его действия. Это сработает, только если таймер всё ещё находится в стадии ожидания.847848### Объекты барьеров849850Добавлено в версии 3.2.851852Этот класс предоставляет простой примитив синхронизации для использования фиксированным числом потоков, которым нужно ждать друг друга. Каждый из потоков пытается пройти барьер, вызывая метод [`wait()`](https://python-all.ru/3.14/library/threading.html#threading.Barrier.wait), и блокируется до тех пор, пока все потоки не вызовут `wait()`. После этого потоки освобождаются одновременно.853854Барьер можно использовать повторно любое количество раз для того же числа потоков.855856В качестве примера приведён простой способ синхронизации потоков клиента и сервера:857858```python859b = Barrier(2, timeout=5)860861def server():862 start_server()863 b.wait()864 while True:865 connection = accept_connection()866 process_server_connection(connection)867868def client():869 b.wait()870 while True:871 connection = make_connection()872 process_client_connection(connection)873```874875#### `class threading.Barrier(parties, action=None, timeout=None)`876877Создаёт объект барьера для *parties* потоков. *action*, если задан, – это вызываемый объект, который будет вызван одним из потоков при освобождении. *timeout* – значение тайм-аута по умолчанию, если не указано другое для метода [`wait()`](https://python-all.ru/3.14/library/threading.html#threading.Barrier.wait).878879#### `wait(timeout=None)`880881Пройти барьер. Когда все потоки-участники барьера вызовут эту функцию, они все освобождаются одновременно. Если указан *timeout*, он используется с приоритетом перед любым значением, переданным конструктору класса.882883Возвращаемое значение – целое число в диапазоне от 0 до *parties* – 1, различное для каждого потока. Это можно использовать для выбора потока, который выполнит специальные вспомогательные действия, например:884885```python886i = barrier.wait()887if i == 0:888 # Выводить это должен только один поток889 print("passed the barrier")890```891892Если конструктору был передан *action*, один из потоков вызовет его перед освобождением. Если этот вызов вызовет ошибку, барьер переводится в состояние сбоя.893894Если вызов истекает по таймауту, барьер переводится в сломанное состояние.895896Этот метод может вызвать исключение [`BrokenBarrierError`](https://python-all.ru/3.14/library/threading.html#threading.BrokenBarrierError), если барьер сломан или сброшен, пока поток ожидает.897898#### `reset()`899900Возвращает барьер в исходное пустое состояние. Любые потоки, ожидающие его, получат исключение [`BrokenBarrierError`](https://python-all.ru/3.14/library/threading.html#threading.BrokenBarrierError).901902Обратите внимание, что использование этой функции может потребовать внешней синхронизации, если есть другие потоки, состояние которых неизвестно. Если барьер сломан, возможно, лучше просто оставить его и создать новый.903904#### `abort()`905906Переводит барьер в сломанное состояние. Это приводит к тому, что любые активные или будущие вызовы [`wait()`](https://python-all.ru/3.14/library/threading.html#threading.Barrier.wait) завершатся ошибкой с [`BrokenBarrierError`](https://python-all.ru/3.14/library/threading.html#threading.BrokenBarrierError). Используйте это, например, если один из потоков необходимо прервать, чтобы избежать взаимоблокировки приложения.907908Возможно, предпочтительнее просто создать барьер с разумным значением *timeout*, чтобы автоматически защититься от сбоя одного из потоков.909910#### `parties`911912Количество потоков, необходимое для прохождения барьера.913914#### `n_waiting`915916Количество потоков, ожидающих в данный момент на барьере.917918#### `broken`919920Логическое значение, которое равно `True`, если барьер находится в сломанном состоянии.921922#### `exception threading.BrokenBarrierError`923924Это исключение, подкласс [`RuntimeError`](https://python-all.ru/3.14/library/exceptions.html#RuntimeError), вызывается, когда объект [`Barrier`](https://python-all.ru/3.14/library/threading.html#threading.Barrier) сбрасывается или ломается.925926## Использование блокировок, условий и семафоров в операторе `with`927928Все объекты, предоставляемые этим модулем, которые имеют методы `acquire` и `release`, могут использоваться как контекстные менеджеры для оператора [`with`](https://python-all.ru/3.14/reference/compound_stmts.html#with). Метод `acquire` будет вызываться при входе в блок, а `release` – при выходе из блока. Поэтому следующий фрагмент:929930```python931with some_lock:932 # выполнить какие-то действия...933```934935эквивалентно:936937```python938some_lock.acquire()939try:940 # выполнить какие-то действия...941finally:942 some_lock.release()943```944945В настоящее время объекты [`Lock`](https://python-all.ru/3.14/library/threading.html#threading.Lock), [`RLock`](https://python-all.ru/3.14/library/threading.html#threading.RLock), [`Condition`](https://python-all.ru/3.14/library/threading.html#threading.Condition), [`Semaphore`](https://python-all.ru/3.14/library/threading.html#threading.Semaphore) и [`BoundedSemaphore`](https://python-all.ru/3.14/library/threading.html#threading.BoundedSemaphore) могут использоваться как контекстные менеджеры оператора [`with`](https://python-all.ru/3.14/reference/compound_stmts.html#with).946