Learn And Life.

Thread local storage

数据类型

首先看下数据类型的分类,根据是单线程还是多线程,可以分为以下几类

1
2
3
全局数据
局部数据
线程特定数据(TSD)

全局数据和局部数据比较好理解,但是线程特定数据是什么?独立于线程的数据,也就是说只有某个线程可以访问,其它线程不可以访问,实现某个线程内,函数调用之间的共享,也就是线程全局数据

POSIX系统

KEY数据结构数组(至少128个TSD)

KEY数组
标志0
析构函数指针0 —– > 线程0 pthread_key_t
标志1
析构函数指针1 —– > 线程1 pthread_key_t
标志2
析构函数指针2 —– > 线程2 pthread_key_t
………….
标志127
析构函数指针127 —– > 线程127 pthread_key_t
1
2
标志: 是否已经被使用 (每次调用pthread_key_create创建一个新的TSD时,系统都会搜索key结构数组,找出其中未使用的元素,并通过pthread_key_t返回)
析构函数指针: 指向一个析构函数,用户线程结束时后期处理(析构函数参数是一个指向TSD的指针)

每一个TSD由标志字段和析构函数指针组成

进程数据结构

Pthread结构
指针null
指针null
指针null
………….
指针null

其中KEY数组中已分配的key的标志字段,都会跟Pthread结构相关联,而Pthread中存放指向实际数据的指针,也就是说进程维护KEY结构数组,而线程维护Pthread结构数组

函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <pthread.h>
/**
*param 1:一个键值指针
*param 2: 一个destructor函数,如果这个参数不为空,那么每当线程结束时,系统将调用这个函数来释放绑定在这个键上的内存快
**/
int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));
/* 注销一个TSMG_STATIC(id, type, element)
(TSRMG_BULK_STATIC(id, type)→element)
int pthread_key_delete(pthread_key_t key);
/* 读取变量的地址 */
void *pthread_getspecific(pthread_key_t key);
/* 存储变量的地址, 将普通变量转换成TSD */
int pthread_setspecific(pthread_key_t key, const void *value);

PHP中的多线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* Thread local storage */
static pthread_key_t tls_key;
# define tsrm_tls_set(what) pthread_setspecific(tls_key, (void*)(what))
# define tsrm_tls_get() pthread_getspecific(tls_key)
#elif defined(TSRM_ST)
static int tls_key;
# define tsrm_tls_set(what) st_thread_setspecific(tls_key, (void*)(what))
# define tsrm_tls_get() st_thread_getspecific(tls_key)
#elif defined(TSRM_WIN32)
static DWORD tls_key;
# define tsrm_tls_set(what) TlsSetValue(tls_key, (void*)(what))
# define tsrm_tls_get() TlsGetValue(tls_key)
#elif defined(BETHREADS)
static int32 tls_key;
# define tsrm_tls_set(what) tls_set(tls_key, (void*)(what))
# define tsrm_tls_get() (tsrm_tls_entry*)tls_get(tls_key)
#else
# define tsrm_tls_set(what)
# define tsrm_tls_get() NULL

由此可见,tsrm_tls(Thread local storage)对象,实现的只是将普通变量,转换成TSD的处理!

PHP中的相关的宏和函数

1
2
3
4
5
6
7
8
9
#define ZEND_TSRMLS_CACHE TSRMLS_CACHE
#define TSRMLS_CACHE_UPDATE() TSRMLS_CACHE = tsrm_get_ls_cache()
#define TSRMG_BULK_STATIC(id, type) ((type) (*((void ***) TSRMLS_CACHE))[TSRM_UNSHUFFLE_RSRC_ID(id)])
#define TSRMG_STATIC(id, type, element) (TSRMG_BULK_STATIC(id, type)->element)
void *tsrm_get_ls_cache(void)
{
return tsrm_tls_get();
}