php线程安全的问题

php 多线程有什么问题?php

线程的并发问题。html

在多线程系统中,进程保留着资源全部权的属性,而多个并发执行流是执行在进程中运行的线程。如Apache2 中的woker,主控制进程生成多个子进程,每一个子进程中包含固定的线程数,各个线程独立地处理请求。一样,为了避免在请求到来时再生成线程,MinSpareThreads和MaxSpareThreads设置了最少和最多的空闲线程数;而MaxClients设置了全部子进程中的线程总数。若是现有子进程中的线程总数不能知足负载,控制进程将派生新的子进程。数组

当PHP运行在如上相似的多线程服务器时,此时的PHP处在多线程的生命周期中。在必定的时间内,一个进程空间中会存在多个线程,同一进程中的多个线程公用模块初始化后的全局变量,若是和PHP在CLI模式下同样运行脚本,则多个线程会试图读写一些存储在进程内存空间的公共资源(如在多个线程公用的模块初始化后的函数外会存在较多的全局变量),安全

 

此时这些线程访问的内存地址空间相同,当一个线程修改时,会影响其它线程,这种共享会提升一些操做的速度,可是多个线程间就产生了较大的耦合,而且当多个线程并发时,就会产生常见的数据一致性问题或资源竞争等并发常见问题,好比屡次运行结果和单线程运行的结果不同。服务器

 

 

 

 

 

php 线程安全版本 如何实现的?多线程

PHP引入了TSRM: 线程安全资源管理器(Thread Safe Resource Manager)。并发

TRSM 的实现代码在 PHP 源码的 /TSRM 目录下,调用随处可见,一般,咱们称之为 TSRM 层。通常来讲,TSRM 层只会在被指明须要的时候才会在编译时启用(好比,Apache2+worker MPM,一个基于线程的MPM),由于Win32下的Apache来讲,是基于多线程的,因此这个层在Win32下老是被开启的。函数

 

进程保留着资源全部权的属性,线程作并发访问,PHP中引入的TSRM层关注的是对共享资源的访问,这里的共享资源是线程之间共享的存在于进程的内存空间的全局变量。当PHP在单进程模式下时,一个变量被声明在任何函数以外时,就成为一个全局变量。spa

PHP解决并发的思路很是简单,既然存在资源竞争,那么直接规避掉此问题,将多个资源直接复制多份,多个线程竞争的全局变量在进程空间中各自都有一份,各作各的,彻底隔离。以标准的数组扩展为例,首先会声明当前扩展的全局变量,而后在模块初始化时会调用全局变量初始化宏初始化array的,好比分配内存空间操做。线程

这里的声明和初始化操做都是区分ZTS和非ZTS,对于非ZTS的状况,直接就是声明变量,初始化变量。对于ZTS状况,PHP内核会添加TSRM,对应到这里的代码就是声明时再也不是声明全局变量,而是用ts_rsrc_id代码,初始化是再也不是初始化变量,而是调用ts_allocate_id函数在多线程环境中给当前这个模块申请一个全局变量并返回资源ID。

资源ID变量名由模块名和global_id组成。它是一个自增的整数,整个进程会共享这个变量,在进程SAPI初始调用,初始化TSRM环境时, id_count做为一个静态变量将被初始化为0。这是一个很是简单的实现,自增。确保了资源不会冲突,每一个线程的独立。

 

参考文档:

http://www.laruence.com/2008/08/03/201.html

http://www.javashuo.com/article/p-vwmjwcwp-d.html

相关文章
相关标签/搜索