Extending.and.Embedding.PHP读书笔记(3)-Zend线程安全

    Php在其诞生初期,作为一个单进程的CGI程序并没有考虑线程安全,因为没有任何进程能够比一个请求生存期更长。所以一个内部变量能够声明在一个全局范围内,并且可以任意更改,只要它被确切的初始化了。任何没被清理的资源都会随着cgi进程的结束而被释放。

    多进程的web server的出现并没有促使TSRM这层的出现,真正促使该层出现的是多线程web server的出现。

    非线程的程序中,php仅仅为该进程声明一个变量存储空间就行了。多线程的程序中,则需要为每个线程分配独立的变量存储空间。

    php专门有一个线程安全的数据池来保存多线程声明的变量数据
下面是声明线程安全的全局变量
typedef struct {
    int sampleint;
    char *samplestring;
} php_sample_globals;
int sample_globals_id;
PHP_MINIT_FUNCTION(sample)
{
    ts_allocate_id(&sample_globals_id,
        sizeof(php_sample_globals),
        (ts_allocate_ctor) php_sample_globals_ctor,
        (ts_allocate_dtor) php_sample_globals_dtor);
    return SUCCESS;
}
我们在程序中这样调用上述struct php_sample_globals的sampleint,SAMPLE_G(sampleint) = 5,这个代码最终是:(((php_sample_globals*)(*((void ***)tsrm_ls))[sample_globals_id-1])->sampleint =
5;

没有线程安全的声明和使用如下:
typedef struct {
    int sampleint;
    char *samplestring;
} php_sample_globals;
php_sample_globals sample_globals;
PHP_MINIT_FUNCTION(sample)
{
    php_sample_globals_ctor(&sample_globals TSRMLS_CC);
    return SUCCESS;
}

SAMPLE_G(sampleint) = 5;最终调用的是sample_globals.sampleint = 5

如何开启或者关闭线程安全呢?
在编译时用enable-maintainer-zts选项。在代码中如果要测试是否开启线程安全,使用#ifdef ZTS

当线程安全开启时,一个特殊的指针,叫做tsrm_ls便加到了大多数内部函数的原型里,正是这个指针使得PHP能够区分附着于不同线程的变量的值
#define TSRMLS_D     void ***tsrm_ls
#define TSRMLS_DC     , void ***tsrm_ls
#define TSRMLS_C     tsrm_ls
#define TSRMLS_CC     , tsrm_ls

下面第一行是声明,第二行是使用。但是如果没有开启线程安全,则最后一个参数是没有用的
int php_myext_action(int action_id, char *message TSRMLS_DC);
php_myext_action(42, "The meaning of life" TSRMLS_CC);


 TSRMLS_FETCH()在使用外部函数库时存取变量的宏,但是需要谨慎的使用这个宏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值