您的位置:首页 > 编程语言 > PHP开发

理解php内核的 引用计数器与写时复制

2017-05-27 22:18 567 查看
zval结构中有以下两个成员变量用于引用计数器:
is_ref:BOOL值,标识变量是否是引用集合
refcount:计算指向引用集合的变量个数

写时复制:就是当变量的值改变时才进行内存的复制。
<?php

$a = "this a test ";

xdebug_debug_zval('a');

$b = $a;

xdebug_debug_zval('a');

$a = "changed the test value";

xdebug_debug_zval('a');

执行结果:
a: (refcount=1, is_ref=0),  (length=12)
a:
(refcount=2, is_ref=0),  (length=12)
a:
(refcount=1, is_ref=0),  (length=22)
当$a的值赋给变量$b时,变量$a的refcount增加1,所以这时候变量$a跟变量$b是指向同一内存块的;
改变$a的值时,发现refcount的值变回1,所有这时候变量$a和$b 指向不同的内存块,这就是写时复制。就是两个指向同一内存块的变量,当其中一个变量的发生变化,才会另外创建一个内存块去保存新的值。

写时复制也是一种引用,只不过这种引用会受到变量值的改变而破坏罢了。

显式引用情况:
<?php

$a = 1;

xdebug_debug_zval('a');

$b = & $a;

xdebug_debug_zval('a');

$b += 5;

xdebug_debug_zval('a');

执行结果:
a: (refcount=1, is_ref=0),
a:
(refcount=2, is_ref=1),
a:
(refcount=2, is_ref=1),
is_ref字段等于1,表示此变量被引用。refcount也相应+1

在PHP内核中通过以下代码判断是否复制变量:
if ((*varval->is_ref || (*varval)->refcount<2)) {
return *varval;

}

当变量被引用,或者引用计数器小于2时会直接返回变量的指针(直接返回变量的实体,而不复制变量的值)。当修改一个被引用变量的值时,所有引用他的变量其值也会被修改,因为他们指向同一个zval容器。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: