PHP 8.5.0 Alpha 2 available for testing

Класс Swoole\Coroutine\Lock

(No version information available, might only be in Git)

Введение

В Swoole 6.0.1 для корутин, или сопрограмм, появились блокировки, которые поддерживают разделение между процессами или между потоками. Неблокирующее поведение таких блокировок повышает эффективность синхронизации корутин в многопроцессных и многопоточных средах.

При компиляции с параметром --enable-iouring и при поддержке ядром Linux функции io_uring futex сопрограммная блокировка модуля Swoole реализует синхронизацию через фьютекс io_uring. При такой синхронизации сопрограммы ожидают пробуждения блокировки через эффективный механизм организации очередей, который значительно повышает производительность.

Без фьютекса io_uring корутинная блокировка переключается на механизм экспоненциально нарастающего ожидания, при котором время ожидания увеличивается на 2^n миллисекунд, где n — количество отказов, после каждой неудачной попытки захватить блокировку. Хотя такой подход исключает активное ожидание, он создаёт дополнительную нагрузку на планировщик процессов и увеличивает задержки.

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

Внимание

Лучше не создавать блокировки в callback-функциях наподобие onReceive, поскольку это приведёт к неконтролируемому росту потребления памяти или даже вызовет утечки памяти.

Внимание

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

Обзор класса

class Swoole\Coroutine\Lock {
/* Методы */
public __construct(): void
public lock(): bool
public trylock(): bool
public unlock(): bool
}

Примеры

Пример #1 Базовый пример работы с блокировками

<?php

use Swoole\Coroutine\Lock;
use
Swoole\Coroutine\WaitGroup;
use function
Swoole\Coroutine\go;
use function
Swoole\Coroutine\run;

$lock = new Lock();
$waitGroup = new WaitGroup();

run(function() use ($lock, $waitGroup) {
go(function() use ($lock, $waitGroup) {
$waitGroup->add();
$lock->lock();
sleep(1);
$lock->unlock();
$waitGroup->done();
});

go(function() use ($lock, $waitGroup) {
$waitGroup->add();
$lock->lock(); // Дождаться, пока другая сопрограмма освободит блокировку
sleep(1);
$lock->unlock();
$waitGroup->done();
});

echo
'Блокировка приостанавливает только текущую корутину, но не останавливает весь процесс';
$waitGroup->wait();
});

Содержание

Добавить

Примечания пользователей

Пользователи ещё не добавляли примечания для страницы
To Top