Как защитить критическую секцию в PHP?

Я немного поискал по этой теме, но не нашел ничего ценного.

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

В Java мы синхронизировали. В C# у нас есть lock.

В PHP, как это сделать?


person Morgan Cheng    schedule 05.04.2010    source источник
comment
Какая ситуация вас беспокоит? Я не уверен, что вы считаете проблемой PHP.   -  person cletus    schedule 05.04.2010
comment
Это проблема, если у вас есть много изменений состояния в параллельных неупорядоченных запросах. Вам необходимо сериализовать изменения состояния для сеанса, чтобы предотвратить перезапись состояния друг друга запросами.   -  person pestilence669    schedule 05.04.2010


Ответы (3)


Используйте для этого семафоры.

person Ignacio Vazquez-Abrams    schedule 05.04.2010

Поскольку PHP-скрипты не являются многопоточными, я не считаю, что критические секции имеют значение. Я согласен с тем, что у вас есть состояние гонки, потому что несколько экземпляров выполняются параллельно, но критическая секция не решит вашу проблему.

Если вы используете обработчик сеанса на основе файлов, вы можете попробовать базовый flock(). Если вы используете базу данных, вы можете попробовать использовать собственный механизм блокировки (предпочтительно на уровне строк). Если вы используете memcached, вы можете попробовать реализовать распределенную систему блокировки.

Вы не захотите применять блокировку слишком широко. Вам нужно что-то максимально детализированное (возможно, привязанное к идентификатору сеанса). Если вы попытаетесь сериализовать все поведение сеанса, вы создадите серьезное узкое место.

В мире баз данных (и в других местах) оптимистичные «замки» — это часто все, что вам нужно. Они включают простой счетчик, который увеличивается. Если счетчик выключен (коллизия), запись не обновляется, и вы можете повторно получить и применить свои различия по мере необходимости. Это вещь типа UPDATE table WHERE count = lastcount в сочетании с повторной попыткой. Это часто помогает.

Конечно, вы можете использовать блокировку файлов, семафоры SYSV (экономно) и множество других методов для достижения этой цели. Просто помните, это звучит как состояние гонки, но это не имеет ничего общего с потоками.

person pestilence669    schedule 05.04.2010
comment
Спасибо за ваш ответ. Я понимаю, что в PHP нет потоковой модели, такой как Java и C#. Но в тех же случаях я хочу, чтобы к одному объекту сеанса обращались только с помощью одной обработки запроса (в PHP, процессе или потоке). Итак, вы предлагаете не сериализовать все поведение сеанса. Небольшая степень детализации блокировки обеспечивает высокую производительность, но я просто сомневаюсь, что это усложнит код. Просто блокировать сеанс на уровне запроса (например, обработчик сеанса по умолчанию) глупо, но просто. - person Morgan Cheng; 05.04.2010
comment
Это конечно просто, но немного лениво. Почему бы не заблокировать идентификатор сеанса? На одном сервере или в сегментированном облаке вы можете легко заблокировать некоторый /tmp/XXX файл для каждого сеанса. Это практически решило бы вашу проблему. - person pestilence669; 20.04.2010

В большинстве случаев вам не нужно иметь дело с критическим разделом, потому что PHP не имеет модели потоков (без разделения памяти). Я даже не думаю, что semephores вам доступен. PHP использует "архитектуру без совместного использования", как вы можете видеть на слайды создателя PHP Расмуса Лердорфа. Это означает, как вы можете видеть на слайде, что

Общие данные передаются на уровень хранилища данных

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

Надеюсь, это немного ответит на ваш вопрос.

person Alfred    schedule 05.04.2010
comment
Несмотря на то, что PHP является архитектурой без совместного использования, переменные сеанса совместно используются несколькими запросами. Там еще возможна критическая секция. - person Morgan Cheng; 05.04.2010
comment
Сессия распределяется между несколькими запросами, я думаю, но они являются безопасным стандартом? Как получить условия гонки? - person Alfred; 05.04.2010