PHP同一进程下的多个线程会试图读写一些存储在 进程内存空间 的公共资源,此时这些线程访问的内存地址空间相同,当一个线程修改时,会影响其它线程,这种共享会提高一些 操作的速度, 但是多个线程间就产生了较大的耦合,并且当多个线程并发时,就会产生常见
PHP同一进程下的多个线程会试图读写一些存储在进程内存空间的公共资源,此时这些线程访问的内存地址空间相同,当一个线程修改时,会影响其它线程,这种共享会提高一些
操作的速度, 但是多个线程间就产生了较大的耦合,并且当多个线程并发时,就会产生常见的数据一致性问题或资源竞争等并发常见问题。
我的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; };
(图片出处: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; 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; } </id_count>
---------------------
珠玉在前:
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