Thread Safe и Non-Thread Safe в PHP: что выбрать и как не ошибиться?

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Что такое thread safe или non-thread safe в PHP? Разбираемся раз и навсегда

Если вы хоть раз устанавливали PHP на Windows или настраивали веб-сервер, то наверняка видели загадочные аббревиатуры TS и NTS в названиях дистрибутивов. Или читали предупреждения в документации: «Выберите thread-safe или non-thread-safe версию». И тут же возникал вопрос: «А что это вообще такое? И что будет, если выбрать не то?»

Эта статья — ваш навигатор в мире потокобезопасности PHP. Мы разберёмся, чем отличаются thread safe (TS) и non-thread safe (NTS) сборки, когда нужна каждая из них, и как не попасть в ловушку несовместимости расширений. Поехали!

Коротко о главном: что такое потокобезопасность?

Представьте, что PHP — это повар на кухне. А каждый запрос к вашему сайту — это новый заказ. В non-thread safe режиме каждый заказ готовит отдельный повар в своей личной кухне. Они не мешают друг другу, потому что у каждого свои ножи, кастрюли и продукты. Никакой общей памяти — никаких конфликтов.

В thread safe режиме у вас один повар, но он работает с несколькими руками (потоками). Все руки делят одну кухню, одни инструменты и одну память. И тут главное — не схватить один и тот же нож одновременно. Чтобы этого не случилось, нужны блокировки и синхронизация — это и есть потокобезопасность (thread safety).

Простыми словами: Thread Safe (TS) — PHP умеет работать в многопоточной среде, где один процесс обрабатывает несколько запросов одновременно. Non-Thread Safe (NTS) — PHP работает в однопоточном режиме, где каждый запрос — это отдельный процесс.

Когда и почему появились TS и NTS версии?

Исторически PHP развивался как модуль для Apache (mod_php). Apache умеет работать в двух режимах: prefork (один процесс на запрос) и worker (один процесс с множеством потоков). Для prefork'а потокобезопасность не нужна — каждый запрос изолирован. А вот для worker'а — критична.

Позже, с ростом популярности FastCGI (PHP-FPM) и Nginx, стало ясно: в этих сценариях многопоточность внутри PHP не используется. FastCGI запускает отдельные процессы, и каждый из них работает независимо. Зачем тогда тащить за собой тяжеловесный код блокировок? Так появились облегчённые non-thread safe сборки.

Как определить, какая версия PHP у вас установлена?

Самый простой способ — запустить в консоли или в PHP-скрипте:

<?php
phpinfo();
?>

Найдите строку Thread Safety. Если там написано enabled — у вас TS версия. Если disabled — NTS.

Второй способ — посмотреть на вывод команды php -i | findstr "Thread" (Windows) или php -i | grep Thread (Linux/macOS).

Визуальные отличия в названиях дистрибутивов

На официальном сайте windows.php.net вы увидите примерно такие названия:

  • php-8.3.0-Win32-vs16-x64.zip — обычно это NTS (но нужно смотреть описание)
  • php-8.3.0-Win32-vs16-x64-ts.zip — а вот TS версия, здесь явно указано -ts

На Linux сборки обычно не разделяют — там используется один бинарник, собранный с поддержкой потоков (ZTS — Zend Thread Safety), но реально многопоточность включается только при использовании Apache worker.

Практические сценарии: когда выбирать TS, а когда NTS?

Сценарий 1: Apache + mod_php (worker MPM)

Если вы используете Apache с worker или event MPM (многопоточные режимы) — вам строго нужна TS версия PHP. Иначе — фатальные ошибки, падения сервера и потеря данных. Выглядеть это будет примерно так:

[error] AH00052: child pid 12345 exit signal Segmentation fault (11)

Неприятно, правда?

Сценарий 2: Apache + mod_php (prefork MPM)

Если вы используете prefork (каждый запрос — отдельный процесс) — можно использовать любую версию. Но NTS будет работать немного быстрее, так как не тратит ресурсы на блокировки. На практике разница незаметна, но если вы собираете PHP сами — выбирайте NTS.

Сценарий 3: Nginx + PHP-FPM

Это самый популярный стек в 2024 году. PHP-FPM всегда работает как FastCGI-процесс, и каждый воркер — это отдельный процесс. Многопоточности внутри PHP нет. Значит, нужна NTS версия. Использовать TS здесь — всё равно что ехать на танке по асфальту: можно, но зачем?

Сценарий 4: IIS (Internet Information Services)

На Windows с IIS ситуация чуть сложнее. Если вы используете PHP через FastCGI (рекомендуемый способ) — берите NTS. Если используете старый добрый ISAPI — нужен TS, но ISAPI считается устаревшим.

Пример кода: как проверить потокобезопасность и её влияние

Давайте напишем простой скрипт, который покажет, как ведёт себя глобальная переменная в многопоточном окружении:

<?php
// Пример для TS версии PHP
$counter = 0;

function increment() {
    global $counter;
    // В TS версии доступ к $counter должен быть защищён мьютексом
    // Но PHP сам не предоставляет примитивов синхронизации!
    $counter++;
    return $counter;
}

echo increment(); // Может быть 1, а может и 2, если другой поток вмешался
?>

Важно: сам PHP не даёт встроенных средств для синхронизации потоков на уровне кода (нет мьютексов, семафоров в стандартной поставке). Поэтому даже в TS версии вы не можете просто так разделять данные между потоками — нужно использовать расширения вроде pthreads (до PHP 7.4) или parallel (с PHP 8.0+).

Как отличить TS и NTS в коде?

<?php
// Проверяем, собран ли PHP с поддержкой потоков (ZTS)
if (defined('ZEND_THREAD_SAFE') && ZEND_THREAD_SAFE) {
    echo "У вас Thread Safe (ZTS) версия PHP.\n";
} else {
    echo "У вас Non-Thread Safe (NTS) версия                

Блоги

Рекомендаций по книгам