Подтвердить что ты не робот

Синхронизированные функции в PHP

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

4b9b3361

Ответ 1

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

Ответ 2

Вы можете использовать внешнюю блокировку - например, блокировку файла через flock. Создайте файл где-нибудь и script заблокируйте его. Вы также можете использовать семафоры, но это только Unix.

Ответ 3

Я не могу придумать никаких проблем, с которыми вы столкнулись. Однако однажды мне пришлось написать PHP script, который выполнял сложные вычисления, и я должен был убедиться, что он не был выполнен одновременно двумя пользователями. Для этого я создал пустой файл в начале script и удалил его, когда вычисления были завершены. Конечно, script проверял, существовал ли файл до его начала.

Ответ 4

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

Ответ 5

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

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

Ответ 6

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

В качестве примера: я использую Symfony с ORM Doctrine, поэтому мой код фиксации обычно выглядит примерно так:

$conn = Doctrine_Manager::connection();
$conn->beginTransaction();
try {
// .. database code ..
    $conn->commit();
} catch(Doctrine_Exception $ex) {
    $conn->rollback();
    // additional exception handling
}

Теперь это не будет препятствовать пользователям сбивать друг друга, если они будут изменять одну и ту же запись одновременно; однако он будет следить за тем, чтобы база данных оставалась последовательной - то есть, изменения пользователя А вступают в силу, а изменения пользователя B вступают в силу, но никогда не зависает пользователь A и User B в зависимости от настроения БД.