Прочитайте некоторые тексты о привязке PHP.
Они все, главным образом, прямо к http://php.net/manual/en/function.flock.php.
Эта страница говорит об открытии файла на жестком диске!!
Это действительно так? Я имею в виду, это делает блокировку действительно дорогой - это означает каждый раз, когда я хочу заблокировать, я должен буду получить доступ к жесткому диску), =
Может больше успокаивать меня восхитительными новостями?
Править:
Из-за некоторых ответов я имею здесь, я хочу спросить это;
Мой сценарий будет работать только одним потоком или несколькими? Поскольку, если это одним затем, мне, очевидно, не нужно взаимное исключение. Существует ли краткий ответ?
Что точно я пытаюсь сделать
Спрошенный ircmaxell.
Это - история:
У меня есть два FTP-сервера. Я хочу смочь показать в моем веб-сайте, сколько подключенных пользователей онлайн.
Так, я думал, что эти FTP-серверы будут "POST" их статистика к определенной странице Сценария PHP. Давайте предположим, что URL этой страницы является "http://mydomain.com/update.php".
На основной странице веб-сайта ("http://mydomain.com/index.php") я отображу кумулятивную статистику (подключенные пользователи).
Именно.
Моя проблема состоит в том, что я не уверен, будет ли, когда один FTP-сервер обновляет его статистику, в то время как другой делает это также, информация смешана.
Как когда многопоточность; Два потока увеличивают некоторую "международную" переменную одновременно. Этого не произойдет как ожидалось, если Вы не будете синхронизировать между ними.
Так, у меня будет проблема? Да, нет, возможно?
Возможное решение
Думая трудно обо всем этом день долго, у меня есть идея здесь, и я хочу, чтобы Вы дали свое мнение.
Как сказано эти FTP-серверы отправят свою статистику, один раз в 60 секунд.
Я думаю о наличии этого файла "stats.php".
Это будет включено в сценарий обновления, что FTP-серверы переходят к ("update.php") и на уровне "index.php" страницы, где посетители видят, сколько пользователей онлайн.
Теперь, когда FTP-сервер обновляет, сценарий в "update.php" изменит "stats.php" с новой кумулятивной статистикой.
Сначала это прочитает статистику, включенную в "stats.php", затем накопится и затем перепишет тот файл.
Если я не буду ошибочным PHP, то обнаружит, что файл ("stats.php") изменяется, и загрузите новый. Корректный?
Что ж, большая часть PHP выполняется в другом пространстве процесса (существует несколько реализаций потоковой передачи). Самый легкий - это стадо. Гарантированно работает на всех платформах.
Однако, если вы компилируете с поддержкой, вы можете использовать еще несколько вещей, например, расширение Semaphore. (Скомпилируйте PHP с помощью --enable-sysvsem). Затем вы можете сделать что-то вроде (обратите внимание, sem_acquire () должен блокироваться. Но если по какой-то причине он не может этого сделать, он вернет false):
$sem = sem_get(1234, 1);
if (sem_acquire($sem)) {
//successful lock, go ahead
sem_release($sem);
} else {
//Something went wrong...
}
Другие варианты, которые у вас есть, - это MySQL блокировки на уровне пользователя. GET_LOCK ('name', 'timeout')
, или создание собственного с помощью чего-то вроде APC или XCache (обратите внимание, это не будет настоящей блокировкой, поскольку условия гонки могут быть созданы там, где кто-то другой получит между вашим чеком и принятием замка).
Edit: Чтобы ответить на ваш отредактированный вопрос:
Все зависит от конфигурации вашего сервера. PHP может выполняться в многопоточном режиме (где каждый запрос обслуживается отдельным потоком) или может выполняться в нескольких процессах (где каждый запрос обслуживается другим процессом). Все зависит от конфигурации вашего сервера ...
ОЧЕНЬ редко PHP обслуживает все запросы последовательно, и только один процесс (и один поток) обслуживает все запросы. Если вы используете CGI, то по умолчанию он многопроцессорный. Если вы используете FastCGI, скорее всего, это многопроцессорный и многопоточный. Если вы используете mod_php с Apache, это зависит от типа рабочего:
Edit: Чтобы ответить на ваш второй отредактированный вопрос:
Это довольно просто. Сохраните его в файле:
function readStatus() {
$f = fopen('/path/to/myfile', 'r');
if (!$f) return false;
if (flock($f, LOCK_SH)) {
$ret = fread($f, 8192);
flock($f, LOCK_UN);
fclose($f);
return $ret;
}
fclose($f);
return false;
}
function updateStatus($new) {
$f = fopen('/path/to/myfile', 'w');
if (!$f) return false;
if (flock($f, LOCK_EX)) {
ftruncate($f, 0);
fwrite($f, $new);
flock($f, LOCK_UN);
fclose($f);
return true;
}
fclose($f);
return false;
}
function incrementStatus() {
$f = fopen('/path/to/myfile', 'rw');
if (!$f) return false;
if (flock($f, LOCK_EX)) {
$current = fread($f, 8192);
$current++;
ftruncate($f, 0);
fwrite($f, $current);
flock($f, LOCK_UN);
fclose($f);
return true;
}
fclose($f);
return false;
}
PHP не поддерживает многопоточность, каждый запрос (и, следовательно, каждый сценарий PHP) будет выполняться только в одном потоке (или даже в процессе, в зависимости от того, как вы запускаете PHP).
Да, это правда, поскольку PHP управляется Apache, и Apache может организовать потоки выполнения так, как он считает лучшим (см. Различные рабочие модели). Поэтому, если вы хотите получить доступ к ресурсу по одному, вы либо блокируете файл (что хорошо, например, если вы имеете дело с заданиями cron), либо полагаетесь на механизм транзакций базы данных, функции ACID и блокировку ресурсов базы данных, если вы имеете дело с данными.