1.应用场景

主要用于弄清楚为什么会有线程安全与非线程安全的不同语言版本,以及这种情况是不是一直存在,

是否有解决统一的办法吗~

2.学习/操作

1.文档阅读

PHP For Windows: Binaries and sources Releases

PHP: Downloads

PHP 安全更新|PHP 7.4.2 与 PHP 7.3.14,以及 PHP 7.2.27 正式发布

原创|从 PHP Git 源码的查找导致 PHP 安全漏洞的代码变更

php支持多线程吗-PHP问题-PHP中文网

PHP的几种运行模式cli、fpm、apache、zts比较【20210511】 - - 个人主页

https://www.jianshu/p/d83d60feb17e

2.整理输出

2.1 关键点

ZTS -- Zend Thread Safely -- 线程安全

NTS -- Non Thread Ssfely -- 非线程安全

PHP的线程安全与非线程安全版本,只存在与Windows版本中,即常是我们的本地开发环境 [如果您使用mac, 省略这句],结合日常开发中使用的开源组件即可知。

但是在*nix下,PHP确实不存在线程安全版本问题,因为只提供非线程安全版本。

由下可佐证:

至于为什么*nix中为什么没有提供ZTS的PHP版本?

原因见下面的红色文字:

由于与Linux/Unix系统是采用多进程的工作方式, 不同的是Windows系统是采用多线程的工作方式

扩展:线程与进程的区别

操作系统 - 进程 / 线程 / 协程 - 学习/实践_穿素白衫的少年的博客-CSDN博客

2.2 介绍

什么是线程安全?

Thread Safety means that binary can work in a multithreaded webserver context, such as Apache 2 on Windows. Thread Safety works by creating a local storage copy in each thread, so that the data won’t collide with another thread.

翻译:

线程安全意味着二进制文件可以在多线程的Web服务器上下文中工作,如Windows上的Apache2。

线程安全性的工作原理是在每个线程中创建一个本地存储副本,这样数据就不会与另一个线程发生冲突。

线程安全就是能够在多线程环境下正常工作,不会导致不合理的情况发生,导致错误。

这取决于Web Server「Web服务器,如apache-http,nginx,apache-tomcat等」在处理并行访问时是否用到多线程。

?TBD

如果用不到多线程,自然就可以不用保证线程安全,就可以使用NTS版本

反之,则需要使用TS版本

2.3 历史渊源「或者说:一个故事

主角与配角:

PHP与Windows

故事情节:

Windows版的PHP从版本5.2.1开始有Thread Safe(线程安全)和None Thread Safe(NTS,非线程安全)之分。

[插问:php语言诞生于哪一年?1994年产生,1995年发布php 1.0 即第一个正式版本]

从 2000年 10月20日发布的第一个Windows版的PHP3.0.17开始的都是线程安全的版本,「故事总是有原因的,历史总是不会无缘无故

这是由于与Linux/Unix系统是采用多进程的工作方式, 不同的是Windows系统是采用多线程的工作方式

如果在IIS下以CGI方式运行PHP会非常慢,这是由于CGI模式是建立在多进程的基础之上的,而非多线程。一般我们会把PHP配置成以ISAPI的方式来运行,ISAPI是多线程的方式,这样就快多了「当你以为故事有一个好的结局,即将落幕的时候,历史会告诉你,你还是太年轻

但存在一个问题,很多常用的PHP扩展是以 Linux/Unix的多进程思想来开发的,这些扩展在ISAPI的方式运行时就会出错搞垮IIS「如果搞不垮,也可能不会有后面的事情了

因此「实践出'真知'----相对而言在IIS下CGI模式才是PHP运行的最安全方 式,但CGI模式对于每个HTTP请求都需要重新加载和卸载整个PHP环境,其消耗是巨大的。

为了兼顾IIS下PHP的效率和安全「中庸思想,微软 给出了FastCGI的解决方案。

FastCGI可以让PHP的进程重复利用,而不是每一个新的请求就重开一个进程。同时FastCGI也可以允许几个进程同时执行。

这样既解决了CGI进程模式消耗太大的问题,又利用上了CGI进程模式不存在线程安全问题的优势「进程模型运行,自然不存在线程安全」。

因此,如果是使用ISAPI 的方式来运行PHP就必须用Thread Safe(线程安全)的版本;

而用FastCGI模式运行PHP的话就没有必要用线程安全检查了,用None Thread Safe(NTS,非线程安全)的版本能够更好的提高效率。

NTS(None-Thread Safe) 即非线程安全,就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的是脏数据,php以fast-cgi方式运行的时候选择这个版本,具有更好的性能;

PHP官方PHP: Hypertext Preprocessor上关于Windows的版本有4个:

VC9 x86 Non Thread Safe,

VC9 x86 Thread Safe,

VC6 x86 Non Thread Safe,

VC6 x86 Thread Safe;

那么有什么区别呢?

目前最新版本 php7.3.7  四个版本「,64位/32位,线程安全/非线程安全」为 : PHP For Windows: Binaries and sources Releases

VC15 x64 Non Thread Safe (2019-Jul-03 17:49:08)

VC15 x64 Thread Safe (2019-Jul-03 17:49:17)

VC15 x86 Non Thread Safe (2019-Jul-03 17:49:10)

VC15 x86 Thread Safe (2019-Jul-03 17:49:26) 】

1. 支持的服务器不同  // 信息要经过思考处理,才能变成有用的信息与知识「目前看来已有过时」

VC9版本是针对IIS服务器的版本,没有对APACHE的支持,而VC6版本对IIS和apache都提供了支持

VC6 是什么?
VC6 就是 legacy Visual Studio 6 compiler ,就是使用这个编译器编译的。


VC9 是什么?
VC9 就是 the Visual Studio 2008 compiler ,就是用微软的 VS 编辑器编译的。

那我们如何选择下载哪个版本的 PHP 呢?
如果你是在 windows 下使用 Apache+PHP 的,请选择 VC6 版本;
如果你是在 windows 下使用 IIS+PHP 的,请选择 VC9 版本;

2. 运行方式的不同
PHP有2种运行方式:ISAPI「IIS下」和/「CGI」& FastCGI。

ISAPI执行方式是以DLL动态库的形式使用,可以在被用户请求后执行,在处理完一个用户请求后不会马上消失,所以需要进行线程安全检查,这样来提高程序的执行效率,所以如果是以ISAPI来执行PHP,建议选择Thread Safe版本;

而FastCGI执行方式是以单一「进程」线程来执行操作,所以不需要进行线程的安全检查「应为多进程之间的进程干扰,涉及到操作系统,详情请查询资料书籍」,除去线程安全检查的防护,反而可以提高执行效率,所以,如果是以FastCGI来执行PHP,建议选择Non Thread Safe版本。

对于Apache服务器来说一般选择isapi方式,而对于Nginx服务器则选择FastCGI方式。

补充阅读

线程安全就是在多线程环境下也不会出现数据不一致,而非线程安全就有可能出现数据不一致的情况。

线程安全由于要确保数据的一致性,所以对资源的读写进行了控制,换句话说增加了系统开销。

所以在单线程环境中效率比非线程安全的效率要低些,但是如果线程间数据相关,需要保证读写顺序,用线程安全模式

这个主要是针对web server 而言,在windows环境下,如果你使用的web server 是apchae 或者 iis 7以下版本,则应该选择线程安全的安装文件,而如果你使用Fast-cgi模式时,可以选择非线程安全,因为 web sever 本身能保证线程安全。
当然还有二进制文件编译时所使用的编译器:vc9 (vs系列) vc6(gcc)

如楼上所言,是针对web server的,部分web server在处理应用请求的时候是用多线程而非多进程的方式处理,线程方式因为涉及到共享寄存器和内存,所以很容易出错,这个时候程序就需要花一些额外的经历去处理寄存器中的数据一致性,即保证线程安全。
所以是否采用线程安全主要看你的web server所采用的PHP请求处理方式,如果是多线程处理,那么请选择线程安全的,否则选择非线程安全的,如楼上所说Fast-cgi方式可选择非线程安全的.

先从字面意思上理解

None-Thread Safe就是非线程安全,在执行时不进行线程(thread)安全检查;

Thread Safe就是线程安全,执行时会进行线程(thread)安全检查,以防止有新请求就启动新线程的 CGI 执行方式耗尽系统资源。

再来看PHP的两种执行方式:ISAPI和FastCGI。FastCGI执行方式是以单一线程来执行操作,所以不需要进行线程的安全检查,除去线程安全检查的防护反而可以提高执行效率,所以,如果是以 FastCGI(无论搭配 IIS 6 或 IIS 7)执行 PHP ,都建议下载、执行 non-thread safe 的 PHP (PHP 的二進位檔有兩種包裝方式:msi 、zip ,請下載 zip 套件)。而线程安全检查正是为ISAPI方式的PHP准备的,因为有许多php模块都不是线程安全的,所以需要使用Thread Safe的PHP。

2.4 选择

1. 见上面

2. PHP手册给出答案

If you choose to run PHP as a CGI binary, then you won’t need thread safety, because the binary is invoked at each request. For multithreaded webservers, such as IIS5 and IIS6, you should use the threaded version of PHP.

翻译: 如果选择以CGI二进制文件的形式运行PHP,那么就不需要线程安全,因为在每个请求中都会调用该二进制文件。对于多线程Web服务器,如iis5和iis6,应该使用php的线程版本

简单讲:

不论在什么平台、用什么web server,只要是用cgi/fastcgi方式运行PHP,都用非线性安全。

ZTS也简称为TS

补充说明:

Nginx:PHP-FPM/fastcgi配合非线程安全的PHP [详情了解nginx]

IIS:     如果fastcig模式,使用NTS PHP

             如果是SPAI模式,使用TS PHP 

Apache:有两种运行模式,如果用fastcgi模式,则配合非线程安全PHP,

                                            如果用LoadModule模式,则要用线程安全PHP。

                后者应该是大多数Apache使用者的选择.

[组合选择]

要论两者的区别,详细论说起来比较麻烦,从使用者的角度,记住什么时候用哪种版本的区别即可

1、windows + IIS + FastCGI :使用非线程安全版本。

解释:
以FastCGI方式安装PHP时,PHP拥有独立的进程,并且FastCGI是单一线程的,不存在多个线程之间可能引发的相互干扰(这种干扰通常都是由于全局变量[与共享内存是怎么回事? TBD] 和 静态变量导致的)。由于省去了线程安全的检查,因此使用FastCGI方式比ISAPI方式的效率更高一些。

2、windows + IIS + ISAPI :使用线程安全版本。

解释:
PHP以ISAPI方式安装时,PHP没有独立的进程,而是作为DLL被IIS加载运行的,即是依附于Web服务器进程的。当Web服务器运行在多线程模式下(IIS正是这种情况),PHP自然也就运行在多线程模式下。只要是在多线程模式下运行,就可能存在线程安全问题,因此应选择PHP的线程安全版本。

3、windows + Apache + PHP(模块) :使用线程安全版本。

解释:
如果你要在Apache中以模块方式安装PHP,则你应该使用PHP的线程安全的版本。原因是当PHP作为Apache的模块安装时,PHP没有独立的进程,而是作为模块以DLL的形式被加载到Apache中的,是随Apache的启动而启动的,而Windows下的Apache为多线程工作模式,因此PHP自然也就运行在多线程模式下。因此,这种情况下应使用PHP的线程安全版本。

4、windows + Apache + PHP(ISAPI) :使用线程安全版本。

解释:
由于以ISAPI方式来安装PHP时,PHP也没有独立的进程,也是作为模块被加载到Apache中的,因此,同样也需要使用PHP的线程安全版本。
一般不建议在Apache中以ISAPI方式来安装PHP,原因是到目前为止,Apache通过mod_isapi.so模块来实现的ISAPI功能并不完整,并未完整实现微软对ISAPI所制定的全部规范。

5、windows + Apache + PHP(FastCGI) :使用非线程安全版本。

解释:
如果你要在Apache中以FastCGI方式使用PHP,则同在IIS中使用FastCGI的PHP的情况一样,你应该使用PHP的非线程安全的版本。原因是在Apache中以FastCGI方式安装PHP时,PHP拥有独立的进程,并且FastCGI是单一线程的,故应使用PHP的非线程安全版本以提高性能。

官网

后续补充

...

3.问题/补充

1. 如何查看PHP是否TS/NTS版本?

查看phpinfo(), Thread Safety 项, 如果是:enabled,一般来说应该是ts版,否则是nts版。

这里通过命令行模式:

打开cmd, 输入php -r "phpinfo();" 回车, 搜索 Thread Safety 即可.

2. apache 2.x 中, PHP有几种运行方式?  // 20201214

三种方式

1. 模块加载 loadModule

2. ISAPI

3. CGI/Fastcgi

3. PHP 自带的 HTTP Server 是属于什么类型的 ?  // 20201214

线程安全/非线程安全 ??

取决于你安装的是否为线程安全的PHP

4. 问题:什么叫非线程平台,和线程平台?

个人认为,使用线程调用运行的平台,即线程平台

如,Windows就是使用线程进行调度的平台。

如果不是使用线程进行调度的平台,即非线程平台

如,Linux / Mac,使用进程进行调度。

5. 突然想到的几个问题 -- 20221013 

1. PHP的非线程安全和线程安全版本的问题
    1.1 *nix只提供一个PHP版本 --- 非线程安全版本?

    是的,NTS版本,通常是Nginx + PHP-FPM


    1.2 Windows 下提供两个PHP版本 --- 线程安全和线程不安全

     是的,windows下提供两个版本,具体使用哪个版本,则要根据选择的Web Server以及运行的方式

     决定,如果也是,Nginx + PHP-FPM/Fastcgi「多进程模型」,那么也是NTS PHP

     如果Apache,IIS以ISAPI 「多线程模型」方式运行,则需要你使用ZTS PHP。


    1.3 即便使用了线程安全版本的PHP,但是可能也不会启用线程安全开关,为了性能考虑。

     NTS性能更高,因为不用检查线程是否安全,加锁。

     选择了哪种版本的PHP,就确定了,不存在开关。


    1.4 好像php-fpm就是配合nts的php版本?

     是的,*nix或者windows下,Nginx + PHP-FPM + NTS PHP

追加

PHP对多线程的支持不好,几乎没人使用PHP的ZTS版本

4.参考

PHP的线程安全与非线程安全版本的区别-php手册-PHP中文网
PHP的线程安全与非线程安全_天台的云的博客-CSDN博客
multithreading - What is thread safe or non-thread safe in PHP? - Stack Overflow  // key point 第一个回答,需要多读几遍
Don’t Believe The Lies: PHP Isn’t Thread-Safe Yet | The NeoSmart Files // 2008年的一篇文章,主要是说php线程安全是一个lie【谎言】,请不要相信官方的话/
关于PHP线程安全和非线程安全的区别_果果勋的博客-CSDN博客_php线程安全和非线程安全的区别 // os + web server + 运行模式 = 选择php线程/非线程安全版本   简单讲: 就是只要使用到fastCGI或者CGI就选非线程安全版本 

操作系统 - 进程 / 线程 / 协程 - 学习/实践_穿素白衫的少年的博客-CSDN博客 // 进程与线程

后续补充

..。

更多推荐

PHP - 版本选择 - 线程安全与非线程安全 - 学习/实践