Avatar ·

Что такое thread safe и non-thread safe в PHP и как это влияет на работу?

Всем привет! Я только начал изучать PHP глубже и наткнулся на термины "thread safe" и "non-thread safe" при скачивании дистрибутивов PHP. Честно говоря, я запутался. Я пишу обычное веб-приложение на PHP + Apache (mod_php). У меня есть простой скрипт, который считает количество посещений страницы в файле: ```php ``` Вроде всё работает, но я читал, что если использовать thread safety, то могут быть проблемы с гонками данных (race conditions) и переменные могут "пересекаться" между потоками. А если non-thread safe — то всё работает быстрее, но может упасть. Я не понимаю: какой вариант мне выбрать для продакшена? Влияет ли это на работу с базами данных, сессиями или кешированием? И что вообще значит "потокобезопасность" применительно к PHP, если PHP сам по себе однопоточный? Объясните, пожалуйста, на пальцах, с примерами, когда что использовать. Заранее спасибо! <<>>

Краткий ответ: thread safe vs non-thread safe

Выбор между thread safe (TS) и non-thread safe (NTS) зависит исключительно от того, как PHP взаимодействует с веб-сервером. Ниже — подробное объяснение с примерами.

1. Что такое thread safety в PHP?

PHP сам по себе однопоточный — один скрипт выполняется в одном потоке. Проблема thread safety возникает, когда несколько запросов обрабатываются в одном общем процессе (многопоточная модель сервера).

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

2. Когда какой использовать?

Выбирайте NTS, если:

  • Вы используете Apache с mod_php в режиме prefork (по умолчанию) — каждый запрос в отдельном процессе.
  • Вы используете Nginx + PHP-FPM — каждый воркер FPM — отдельный процесс.
  • Ваш сервер — IIS в режиме FastCGI.

Выбирайте TS, если:

  • Вы используете Apache с mod_php в режиме worker или event (многопоточный MPM).
  • Вы используете IIS с модулем ISAPI (устарело).
  • Вы пишете расширения для PHP, которые должны быть потокобезопасными.

3. Пример проблемы с гонками данных

Ваш пример со счётчиком не связан напрямую с thread safety — это проблема синхронизации доступа к файлу. Но вот настоящая проблема TS:

// Пример проблемы с глобальной переменной в многопоточной среде
$GLOBALS['user_count'] = 0;

function processUser($userId) {
    // Без TS два потока могут одновременно прочитать 0 и записать 1
    $GLOBALS['user_count']++;
    // В TS версии доступ к $GLOBALS защищён мьютексом
}

В NTS версии такой код может вызвать повреждение памяти. В TS — будет корректно, но медленнее из-за блокировок.

4. Как проверить, какой у вас PHP?

Выполните в консоли:

php -i | grep "Thread Safety"

Вывод: Thread Safety => enabled (TS) или Thread Safety => disabled (NTS).

5. Влияние на базы данных, сессии и кеш

Thread safety не влияет на работу с внешними ресурсами (БД, Redis, Memcached) — они сами управляют конкуренцией. Сессии в PHP хранятся в файлах — конфликты решаются блокировкой файлов (flock), а не thread safety. Кеш опкодов (OPcache) — это единственный внутренний механизм, который требует TS при многопоточном сервере.

6. Практический совет

Для 99% проектов на PHP (Apache + mod_php prefork, Nginx + PHP-FPM) используйте non-thread safe. Он быстрее, потребляет меньше памяти и не имеет накладных расходов на блокировки. Thread safe нужен только если вы точно знаете, что работаете с многопоточным MPM Apache или пишете PHP-расширение.

Ваш пример со счётчиком лучше переписать с использованием flock() для блокировки файла:

function atomicCounter($file) {
    $fp = fopen($file, 'c+');
    if (flock($fp, LOCK_EX)) {
        $counter = (int)fgets($fp);
        $counter++;
        rewind($fp);
        fwrite($fp, $counter);
        fflush($fp);
        flock($fp, LOCK_UN);
    }
    fclose($fp);
    return $counter;
}

Это решит проблему гонок данных независимо от того, TS у вас или NTS.

<<>>

Альтернативное объяснение: мифы о thread safety

Многие начинающие разработчики путают thread safety PHP с многопоточностью внутри самого скрипта (например, с помощью pthreads или parallel). Это разные вещи:

  • Thread safety (TS/NTS) — как PHP компилируется для работы с веб-сервером.
  • Многопоточные расширения (pthreads, parallel) — позволяют создавать потоки внутри одного PHP-процесса. Для них нужна именно TS-версия PHP.

Если вы не используете pthreads или parallel — вам точно не нужен thread safe. Для обычного веб-приложения NTS будет оптимальным.

Ещё один миф: "NTS опасен, потому что данные могут перемешаться". На самом деле, при процессной модели (prefork, FPM) каждый запрос изолирован на уровне операционной системы. Утечка данных между запросами возможна только при утечках памяти в C-расширениях — это крайне редкий случай.

Рекомендую: скачивайте PHP с официального сайта (windows.php.net) — версия "Non Thread Safe" для Windows и стандартная сборка для Linux (обычно NTS). Если сомневаетесь, смотрите на конфигурацию вашего хостинга — 99% хостингов используют NTS.