【PHP内核学习】线程安全
PHP同一进程下的多个线程会试图读写一些存储在 进程内存空间 的公共资源,此时这些线程访问的内存地址空间相同,当一个线程修改时,会影响其它线程,这种共享会提高一些 操作的速度, 但是多个线程间就产生了较大的耦合,并且当多个线程并发时,就会产生常见
PHP同一进程下的多个线程会试图读写一些存储在进程内存空间的公共资源,此时这些线程访问的内存地址空间相同,当一个线程修改时,会影响其它线程,这种共享会提高一些
操作的速度, 但是多个线程间就产生了较大的耦合,并且当多个线程并发时,就会产生常见的数据一致性问题或资源竞争等并发常见问题。
如果每个线程中对全局变量、静态变量只有读操作,而无写操作,则这些个全局变量就是线程安全的.
为解决线程的并发问题,PHP引入了TSRM: 线程安全资源管理器(Thread Safe Resource Manager)。 TRSM 的实现代码在 PHP 源码的 /TSRM 目录下,我们称之为 TSRM 层。
我的php源码位置(gentoo x86_64 GNU/Linux):
PHP的线程安全策略是将线程的共享资源复制多份,进程中的每个线程各自都有一份共享资源的拷贝,各做各的,完全隔离
原理图:
(图片出处:http://blog.codinglabs.org/uploads/pictures/zend-thread-safety/1.png)
_tsrm_tls_entry(TSRM )结构体:
struct _tsrm_tls_entry { void **storage; int count; THREAD_T thread_id; tsrm_tls_entry *next; };
每个tsrm_tls_entry结构负责表示一个线程的所有全局变量资源,其中thread_id存储线程ID,count记录全局变量数,next指向下一个节点。storage可以看做指针数组,其中每个元素是一个指向本节点代表线程的一个全局变量。最终各个线程的tsrm_tls_entry被组成一个链表结构,并将链表头指针赋值给一个全局静态变量tsrm_tls_table。注意,因为tsrm_tls_table是一个货真价实的全局变量,所以所有线程会共享这个变量,这就实现了线程间的内存管理一致性。
(图片出处:http://blog.codinglabs.org/articles/zend-thread-safety.html)
通过一个ts_allocate_id()函数为新的线程分配一个线程安全资源id(thread safe resource id):
/* allocates a new thread-safe-resource id */ TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor) { int i; TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtaining a new resource id, %d bytes", size)); tsrm_mutex_lock(tsmm_mutex);//互斥锁 /* obtain a resource id */ *rsrc_id = TSRM_SHUFFLE_RSRC_ID(id_count++); //id_count即为当前进程下的线程数量 TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtained resource id %d", *rsrc_id)); /* store the new resource type in the resource sizes table */ if (resource_types_table_size count storage = (void *) realloc(p->storage, sizeof(void *)*id_count); for (j=p->count; jstorage[j] = (void *) malloc(resource_types_table[j].size); if (resource_types_table[j].ctor) { resource_types_table[j].ctor(p->storage[j], &p->storage); } } p->count = id_count; } p = p->next; } } tsrm_mutex_unlock(tsmm_mutex); TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Successfully allocated new resource id %d", *rsrc_id)); return *rsrc_id; }
---------------------
珠玉在前:
1.http://blog.codinglabs.org/articles/zend-thread-safety.html
2.http://blog.csdn.net/hackooo/article/details/8856225
3.http://www.laruence.com/2008/08/03/201.html
上一篇: 有关驱动类名的文章推荐3篇
推荐阅读
-
PHP内核学习教程之php opcode内核实现
-
Windows下的PHP安装文件线程安全和非线程安全的区别
-
php 多线程上下文中安全写文件实现代码
-
Java并发编程学习:线程安全与锁优化
-
PHP 线程安全与非线程安全版本的区别深入解析
-
Windows下的PHP安装文件线程安全和非线程安全的区别
-
PHP内核的学习--创建PHP扩展
-
php 多线程上下文中安全写文件实现代码
-
【linux系统编程学习笔记】第十三节:线程的安全机制3(条件变量)(pthread_cond_wait、pthread_cond_signal、pthread_cond_broadcast)
-
PHP多线程(pthreads)参数传递学习笔记