我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

在做php内核编译的时候,总是有个傻傻不清楚的选项,叫做"线程安全"选项。分别是:“非线程安全nts”和“线程安全ts/zts”。是的,zts就是ts就是“线程安全”,“线程不安全”就是nts。那么,具体上来说,它们到底有啥区别呢?是不是“线程安全”一定比“线程不安全”更好呢?nts不安全的版本可以线上使用么?

苏南大叔:php内核,如何理解ts和nts的区别?如何选择? - phpsrc-nts
php内核,如何理解ts和nts的区别?如何选择?(图4-1)

大家好,这里是苏南大叔的“程序如此灵动”博客,这里讲述苏南大叔和计算机代码的故事。本文讲述,php内核编译的"线程安全"问题。其实,这个内容应该是比较深奥的话题,不过目前以苏南大叔的理解,还只能停留于表面。所以,本文的内容仅供参考。测试环境:phpsrc@7.4.28

写在前面

大部分情况下,phper对于这个“线程安全”的选项,是无感的。所以,它必然不会是个啥大的问题。只是在编译或者使用一些“pecl extension”的时候,会因为“线程安全”这个选项不匹配,导致扩展初始化失败。这个时候,才会想起来看看这个线程安全到底是个啥东东。

名称中文英文
ts/zts线程安全Zend Thread Safe
nts非线程安全None Thread Safe

而且“线程不安全”也并不是如狼似虎的bug存在,而且在某些情况下,官方还推荐使用“非线程安全”(aka:nts)版本的php呢。所以,这个大家最关心的“非线程安全”问题,也并不是啥大事儿。在特定的场景下,线程不安全同时意味着效率的提升。那么,“非线程安全”也是有应用场景的。

苏南大叔:php内核,如何理解ts和nts的区别?如何选择? - fpm-nts
php内核,如何理解ts和nts的区别?如何选择?(图4-2)

线程安全问题,指的就是:多线程环境下如何安全存取公共资源。在C中,当一个变量被声明在任何函数之外时,就成为一个全局变量,这时这个变量会被分配到进程的共享存储空间,不同线程都引用同一个地址空间,因此一个线程如果修改了这个变量,就会影响到全部线程。这看似为线程共享数据提供了便利,但是PHP往往是每个线程处理一个请求,因此希望每个线程拥有一个全局变量的副本,而不希望请求间相互干扰。

早期的PHP往往用于单线程环境,每个进程只启动一个线程,因此不存在线程安全问题。后来出现了多线程环境下使用PHP的场景,因此Zend引入了Zend线程安全机制(Zend Thread Safety,简称ZTS)用于保证线程的安全。

官方态度

至于推荐使用哪款php,这个也是要看官方的态度的,苏南大叔来举例一下官方的相关表述。在windows.php.net上面,有下面的表述,参考下述页面的左侧边栏位置。

苏南大叔:php内核,如何理解ts和nts的区别?如何选择? - 如何选择
php内核,如何理解ts和nts的区别?如何选择?(图4-3)

If you are using PHP as FastCGI with IIS you should use the Non-Thread Safe (NTS) versions of PHP.With Apache, using the apache2handler SAPI, you have to use the Thread Safe (TS) versions of PHP.

意思就是iis下面使用fastcgi,推荐使用nts版本。apache下面,使用sapi方式,推荐ts版本。

TS refers to multithread capable builds. NTS refers to single thread only builds. Use case for TS binaries involves interaction with a multithreaded SAPI and PHP loaded as a module into a web server. For NTS binaries the widespread use case is interaction with a web server through the FastCGI protocol, utilizing no multithreading (but also for example CLI).

意思就是:sapimodule加载php的,用ts版本。fastcgicli形式的,就要用nts版本。对于大家最常见的组合:nginx+php-fpmfpm的全称是FastCGI Process Manager。所以,fastcgi=》nts版本是推荐的。

上边的意思,经过苏南大叔理解组合完成后,是下面这个表格(如有不妥,请留言,谢谢):

组合官方推荐版本
sapits
modulets
apache=>sapits
fastcgints
fpm [最常见]nts
clints
iis=>fastcgints

编译参数

对于configure编译的参数这一步,是可以用来控制到底是zts还是nts的。

前不久苏南大叔编译的phpsrc@7.4.28为例来说,默认是ts版本。如果要编译nts版本的话,需要设置:

configure --disable-zts

当然,参数还是要以--help为准。

configure --help

win环境下:

configure.bat --help

苏南大叔:php内核,如何理解ts和nts的区别?如何选择? - configure--help
php内核,如何理解ts和nts的区别?如何选择?(图4-4)

参考文献

综述

本文仅从表象上进行了分析,并没有深入探讨事情的本质,仅供参考。更多php内核编译的文章,请点击:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   phpsrc