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()在使用外部函数库时存取变量的宏,但是需要谨慎的使用这个宏

发布了17 篇原创文章 · 获赞 1 · 访问量 5万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览