> **Источник:** https://python-all.ru/3.6/library/asyncio-sync.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# 18.5.7. Примитивы синхронизации

**Исходный код:** [Lib/asyncio/locks.py](https://python-all.ru/src/3.6/Lib/asyncio/locks.py)

Блокировки:

- [`Lock`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Lock)
- [`Event`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Event)
- [`Condition`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Condition)

Семафоры:

- [`Semaphore`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Semaphore)
- [`BoundedSemaphore`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.BoundedSemaphore)

API блокировок asyncio было разработано так, чтобы быть близким к классам модуля [`threading`](https://python-all.ru/3.6/library/threading.html#module-threading) ([`Lock`](https://python-all.ru/3.6/library/threading.html#threading.Lock), [`Event`](https://python-all.ru/3.6/library/threading.html#threading.Event), [`Condition`](https://python-all.ru/3.6/library/threading.html#threading.Condition), [`Semaphore`](https://python-all.ru/3.6/library/threading.html#threading.Semaphore), [`BoundedSemaphore`](https://python-all.ru/3.6/library/threading.html#threading.BoundedSemaphore)), но у него нет параметра *тайм-аут*. Функция [`asyncio.wait_for()`](https://python-all.ru/3.6/library/asyncio-task.html#asyncio.wait_for) может использоваться для отмены задачи по тайм-ауту.

## 18.5.7.1. Блокировки

### 18.5.7.1.1. Блокировка

#### `class asyncio.Lock(*, loop=None)`

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

Примитивная блокировка – это примитив синхронизации, который не принадлежит конкретной корутине, когда заблокирован. Примитивная блокировка находится в одном из двух состояний: «locked» или «unlocked».

Она создаётся в разблокированном состоянии. У неё есть два основных метода: [`acquire()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Lock.acquire) и [`release()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Lock.release). Когда состояние разблокировано, acquire() изменяет состояние на заблокированное и возвращается немедленно. Когда состояние заблокировано, acquire() блокируется до тех пор, пока вызов release() в другой корутине не изменит его на разблокированное, затем вызов acquire() сбрасывает его в заблокированное и возвращается. Метод release() следует вызывать только в заблокированном состоянии; он изменяет состояние на разблокированное и возвращается немедленно. При попытке освободить разблокированную блокировку будет возбуждено исключение [`RuntimeError`](https://python-all.ru/3.6/library/exceptions.html#RuntimeError).

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

[`acquire()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Lock.acquire) является корутиной и должна вызываться с `yield from`.

Блокировки также поддерживают протокол менеджера контекста. `(yield from lock)` следует использовать в качестве выражения менеджера контекста.

This class is [не является потокобезопасным](https://python-all.ru/3.6/library/asyncio-dev.html#asyncio-multithreading).

Использование:

```python
lock = Lock()
...
yield from lock
try:
    ...
finally:
    lock.release()
```

Использование менеджера контекста:

```python
lock = Lock()
...
with (yield from lock):
    ...
```

Объекты блокировки можно проверить на состояние блокировки:

```python
if not lock.locked():
    yield from lock
else:
    # блокировка получена
    ...
```

#### `locked()`

Возвращает `True`, если блокировка захвачена.

#### `coroutine acquire()`

Захватить блокировку.

Этот метод блокируется до тех пор, пока блокировка не будет разблокирована, затем устанавливает её в заблокированное состояние и возвращает `True`.

Этот метод является [корутиной](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).

#### `release()`

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

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

При вызове на не заблокированной блокировке возбуждается исключение [`RuntimeError`](https://python-all.ru/3.6/library/exceptions.html#RuntimeError).

Возвращаемое значение отсутствует.

### 18.5.7.1.2. Event

#### `class asyncio.Event(*, loop=None)`

Реализация Event, асинхронный эквивалент [`threading.Event`](https://python-all.ru/3.6/library/threading.html#threading.Event).

Класс, реализующий объекты событий. Событие управляет флагом, который может быть установлен в true с помощью метода [`set()`](https://python-all.ru/3.6/library/stdtypes.html#set) и сброшен в false с помощью метода [`clear()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Event.clear). Метод [`wait()`](https://python-all.ru/3.6/library/asyncio-task.html#asyncio.wait) блокируется до тех пор, пока флаг не станет true. Изначально флаг установлен в false.

This class is [не является потокобезопасным](https://python-all.ru/3.6/library/asyncio-dev.html#asyncio-multithreading).

#### `clear()`

Сбросить внутренний флаг в false. После этого корутины, вызывающие [`wait()`](https://python-all.ru/3.6/library/asyncio-task.html#asyncio.wait), будут блокироваться до тех пор, пока не будет вызван [`set()`](https://python-all.ru/3.6/library/stdtypes.html#set) для повторной установки внутреннего флага в true.

#### `is_set()`

Возвращает `True` тогда и только тогда, когда внутренний флаг равен true.

#### `set()`

Установить внутренний флаг в true. Все корутины, ожидающие его перехода в true, пробуждаются. Корутины, вызывающие [`wait()`](https://python-all.ru/3.6/library/asyncio-task.html#asyncio.wait) после того, как флаг станет true, не будут блокироваться вообще.

#### `coroutine wait()`

Блокироваться до тех пор, пока внутренний флаг не станет true.

Если внутренний флаг уже true при входе, немедленно вернуть `True`. В противном случае блокироваться до тех пор, пока другая корутина не вызовет [`set()`](https://python-all.ru/3.6/library/stdtypes.html#set), чтобы установить флаг в true, затем вернуть `True`.

Этот метод является [корутиной](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).

### 18.5.7.1.3. Condition

#### `class asyncio.Condition(lock=None, *, loop=None)`

Реализация Condition, асинхронный эквивалент [`threading.Condition`](https://python-all.ru/3.6/library/threading.html#threading.Condition).

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

Если аргумент *блокировка* задан и не равен `None`, он должен быть объектом [`Lock`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Lock), и используется в качестве нижележащей блокировки. В противном случае создаётся новый объект [`Lock`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Lock), который используется в качестве нижележащей блокировки.

This class is [не является потокобезопасным](https://python-all.ru/3.6/library/asyncio-dev.html#asyncio-multithreading).

#### `coroutine acquire()`

Захватывает базовую блокировку.

Этот метод блокирует выполнение до тех пор, пока блокировка не будет разблокирована, затем устанавливает её в заблокированное состояние и возвращает `True`.

Этот метод является [корутиной](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).

#### `notify(n=1)`

По умолчанию пробуждает одну корутину, ожидающую на этом условии, если такая есть. Если вызывающая корутина не захватила блокировку на момент вызова этого метода, возбуждается [`RuntimeError`](https://python-all.ru/3.6/library/exceptions.html#RuntimeError).

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

> **Примечание**
>
> Пробуждённая корутина на самом деле не возвращается из своего вызова [`wait()`](https://python-all.ru/3.6/library/asyncio-task.html#asyncio.wait) до тех пор, пока не сможет повторно захватить блокировку. Поскольку [`notify()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Condition.notify) не освобождает блокировку, это должен сделать её вызывающая сторона.

#### `locked()`

Возвращает `True`, если базовая блокировка захвачена.

#### `notify_all()`

Пробуждает все корутины, ожидающие на этом условии. Этот метод действует как [`notify()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Condition.notify), но пробуждает все ожидающие корутины вместо одной. Если вызывающая корутина не захватила блокировку на момент вызова этого метода, возбуждается [`RuntimeError`](https://python-all.ru/3.6/library/exceptions.html#RuntimeError).

#### `release()`

Освобождает базовую блокировку.

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

При вызове на не заблокированной блокировке возбуждается исключение [`RuntimeError`](https://python-all.ru/3.6/library/exceptions.html#RuntimeError).

Возвращаемое значение отсутствует.

#### `coroutine wait()`

Ожидает уведомления.

Если вызывающая корутина не захватила блокировку на момент вызова этого метода, возбуждается [`RuntimeError`](https://python-all.ru/3.6/library/exceptions.html#RuntimeError).

Этот метод освобождает нижележащую блокировку, а затем блокирует выполнение до тех пор, пока он не будет пробуждён вызовом [`notify()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Condition.notify) или [`notify_all()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Condition.notify_all) для той же переменной условия в другой корутине. После пробуждения он повторно захватывает блокировку и возвращает `True`.

Этот метод является [корутиной](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).

#### `coroutine wait_for(predicate)`

Ожидает, пока предикат не станет истинным.

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

Этот метод является [корутиной](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).

## 18.5.7.2. Семафоры

### 18.5.7.2.1. Семафор

#### `class asyncio.Semaphore(value=1, *, loop=None)`

Реализация семафора.

Семафор управляет внутренним счётчиком, который уменьшается при каждом вызове [`acquire()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Semaphore.acquire) и увеличивается при каждом вызове [`release()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Semaphore.release). Счётчик никогда не может опуститься ниже нуля; когда [`acquire()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Semaphore.acquire) обнаруживает, что он равен нулю, он блокирует выполнение, ожидая, пока какая-либо другая корутина вызовет [`release()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Semaphore.release).

Семафоры также поддерживают протокол управления контекстом.

Необязательный аргумент задаёт начальное значение внутреннего счётчика; по умолчанию он равен `1`. Если указанное значение меньше `0`, возбуждается [`ValueError`](https://python-all.ru/3.6/library/exceptions.html#ValueError).

This class is [не является потокобезопасным](https://python-all.ru/3.6/library/asyncio-dev.html#asyncio-multithreading).

#### `coroutine acquire()`

Захватывает семафор.

Если внутренний счётчик больше нуля на входе, уменьшить его на единицу и немедленно вернуть `True`. Если он равен нулю на входе, заблокировать выполнение, ожидая, пока какая-либо другая корутина вызовет [`release()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Semaphore.release), чтобы сделать его больше чем `0`, а затем вернуть `True`.

Этот метод является [корутиной](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).

#### `locked()`

Возвращает `True`, если семафор не может быть захвачен немедленно.

#### `release()`

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

### 18.5.7.2.2. BoundedSemaphore

#### `class asyncio.BoundedSemaphore(value=1, *, loop=None)`

Реализация ограниченного семафора. Наследуется от [`Semaphore`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Semaphore).

Это возбуждает [`ValueError`](https://python-all.ru/3.6/library/exceptions.html#ValueError) в [`release()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Semaphore.release), если при этом значение превысило бы начальное значение.
