Поскольку PHP-скрипты не являются многопоточными, я не верю, что критические разделы актуальны. Я согласен, что у вас есть состояние гонки, потому что несколько экземпляров выполняются параллельно, но критический раздел не решит вашу проблему.
Если вы используете файловый обработчик сеанса, вы можете попробовать базовый flock()
. Если вы используете базу данных, вы можете попробовать использовать собственный механизм блокировки (предпочтительно на уровне строк). Если вы используете memcached, вы можете попробовать реализовать систему распределенной блокировки.
Вы не захотите применять блокировку слишком широко. Вам нужно что-то более гранулярное (возможно, привязанное к идентификатору сеанса). Если вы попытаетесь сериализовать все поведение сеанса, вы создадите большое узкое место.
В мире баз данных (и в других местах) оптимистические «блокировки» - это все, что вам нужно. Они включают в себя простой счетчик, который увеличивается. Если счетчик «выключен», (коллизия) запись не обновляется, и вы можете повторно выбрать и применить свои различия в зависимости от ситуации. Это вещь типа UPDATE table WHERE count = lastcount
в сочетании с повторной попыткой. Это часто помогает.
Конечно, вы можете использовать блокировку файлов, семафоры SYSV (экономно) и множество других методов для достижения этой цели. Просто помните, что это похоже на состояние гонки, но это не имеет никакого отношения к нитям.