【PHP内核学习】线程安全
来源:互联网 发布:毒品是谁发明的知乎 编辑:程序博客网 时间:2024/06/05 05:37
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 < id_count) { resource_types_table = (tsrm_resource_type *) realloc(resource_types_table, sizeof(tsrm_resource_type)*id_count);//重新分配内存 if (!resource_types_table) { tsrm_mutex_unlock(tsmm_mutex); TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate storage for resource")); *rsrc_id = 0; return 0; } resource_types_table_size = id_count; } resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].size = size; resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].ctor = ctor; resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].dtor = dtor; resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].done = 0; /* enlarge the arrays for the already active threads */ for (i=0; i<tsrm_tls_table_size; i++) { tsrm_tls_entry *p = tsrm_tls_table[i]; while (p) { if (p->count < id_count) { int j; p->storage = (void *) realloc(p->storage, sizeof(void *)*id_count); for (j=p->count; j<id_count; j++) { p->storage[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
0 0
- 【PHP内核学习】线程安全
- PHP 源码学习之线程安全
- PHP 源码学习之线程安全
- php线程安全
- php线程安全
- PHP 线程安全,多线程
- 【Java】线程安全学习
- 内核线程学习笔记
- php线程安全 非线程安装区别
- PHP线程安全与非线程安全的区别
- PHP线程安全与非线程安全的区别
- PHP 线程安全与非线程安全版本的区别
- PHP非线程安全与线程安全版本的选择
- php线程安全版本与非线程安全版本
- PHP线程安全与非线程安全安装包选择
- php线程安全与非线程安全安装包选择
- PHP线程安全和非线程安全的区别
- PHP线程安全与非线程安全的区别
- PspGetBaseTrapFrame(x64)
- anroid opencv sample引入问题,比如 unresolved inclusion:<jni.h>
- 关于linux系统中close()方法引发一起“血案”
- 页面注入执行js
- c++类中const static变量初始化
- 【PHP内核学习】线程安全
- Java学习之Iterator(迭代器)的一般用法
- MIPS虚拟地址到物理地址转换过程
- 从代码放置位置上来寻找问题的答案
- 【链表&删除倒数第K个节点】Remove Nth Node From End of List
- 来自stackoverflow的一个关于 python 嵌套类的问题(nested class)
- OpenCV学习笔记(四十五)——小试随机森林(random forest)算法ml
- ffmpeg参数设置
- 追忆那些逝去的开源人