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

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

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

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

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

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

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

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

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

Приветствия, Джейкоб

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

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

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

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