加入收藏 | 设为首页 | 会员中心 | 我要投稿 聊城站长网 (https://www.0635zz.com/)- 智能语音交互、行业智能、AI应用、云计算、5G!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

PHP使用计数实现垃圾回收的具体操作是什么

发布时间:2023-05-19 15:30:56 所属栏目:PHP教程 来源:
导读:关于“PHP引用计数实现垃圾回收的具体操作是什么”的知识有一些人不是很理解,对此小编给大家总结了相关内容,具有一定的参考借鉴价值,而且易于学习与理解,希望能对大家有所帮助,有这个方面学习需要的朋
关于“PHP引用计数实现垃圾回收的具体操作是什么”的知识有一些人不是很理解,对此小编给大家总结了相关内容,具有一定的参考借鉴价值,而且易于学习与理解,希望能对大家有所帮助,有这个方面学习需要的朋友就继续往下看吧。
 
实现说明
 
1、给对象添加引用计数器,每次在某个地方引用计数器的值都会增加。每当引用失效时,计数器的值就会减一。
 
变量value的refcount减一后等于0的话,这个value就会被释放,不是垃圾。垃圾回收器不处理。
 
变量value的refcount减一后大于0以上的话,这个value被认为不能释放,有可能成为垃圾。
 
2、垃圾回收器收集可能的垃圾,达到一定数量后启动垃圾鉴定程序,释放真正的垃圾。
 
实例
 
<?php
 
// PHP垃圾回收机制案例: 参考php手册

// --------------------标量类型--------------------
 
// tip:每个php变量存在一个叫"zval"的变量容器中,该容器中包含变量的类型和值,"is_ref":是否是引用变量,"refcount":引用计数

// ex:生成一个新的 zval容器
 
$a = 'new string';
 
// ex:显示 zval容器 信息
 
xdebug_debug_zval('a'); // a:(refcount=1, is_ref=0),string 'new string' (length=10)

// ex:增加 zval容器的引用计数
 
$c = $b = $a;
 
xdebug_debug_zval('a'); // a:(refcount=3, is_ref=0),string 'new string' (length=10)

xdebug_debug_zval('b'); // b:(refcount=3, is_ref=0),string 'new string' (length=10)
 
xdebug_debug_zval('c'); // c:(refcount=3, is_ref=0),string 'new string' (length=10)
 
// tip:此时只有一个容器, 因为当没必要时,php不会去复制已生成的变量容器
 
// 此时这个变量容器被变量 a ,变量 b和变量c关联.
 
unset($b); // ex:减少引用计数
 
xdebug_debug_zval('a'); // a:(refcount=2, is_ref=0),string 'new string' (length=10)
 
// tip:unset 删除变量时,refcount 变量计数减一,此时只有$a,$b 指向该变量容器

unset($a);
 
unset($c);
 
var_dump($a);
 
// tip:此时 recount为 0,变量被删除
 
// 当recount 变为 0 时,包含类型和值的这个变量容器就会从内存中删除。

// --------------------复合类型--------------
 
echo '--------------复合类型------------<br/>';

$a = array(
 
    'name' => 'junior',
 
    'age'  => 18
 
);
 
xdebug_debug_zval('a');
 
// a:(refcount=1, is_ref=0),
 
// array (size=2)
 
//   'name' => (refcount=1, is_ref=0),string 'junior' (length=6)
 
//   'age' => (refcount=1, is_ref=0),int 18
 
// ex:添加一个已经存在的元素到数组中
 
$a['love'] =  $a['name'];
 
xdebug_debug_zval('a');
 
// a:(refcount=1, is_ref=0),
 
// array (size=3)
 
//   'name' => (refcount=2, is_ref=0),string 'junior' (length=6)
 
//   'age' => (refcount=1, is_ref=0),int 18
 
//   'love' => (refcount=2, is_ref=0),string 'junior' (length=6)
 
// $a = array('one');
 
// xdebug_debug_zval('a');
 
// // $b = &$a;
 
// $c = $a;
 
// $b = &$c;
 
// xdebug_debug_zval('b');
 
// xdebug_debug_zval('c');
 
// xdebug_debug_zval('a');
 
// 清理变量容器问题
 
echo '------------内存泄漏问题-----------<br/>';
 
$a = array('one');
 
xdebug_debug_zval('a');
 
// a:(refcount=1, is_ref=0),
 
// array (size=1)
 
//   0 => (refcount=1, is_ref=0),string 'one' (length=3)

$a[] = &$a;
 
xdebug_debug_zval('a');
 
// a:(refcount=2, is_ref=1),
 
// array (size=2)
 
//   0 => (refcount=1, is_ref=0),string 'one' (length=3)
 
//   1 => (refcount=2, is_ref=1),
 
//     &array
 
// unset($a);
 
// (refcount=1, is_ref=1)=array (
 
//     0 => (refcount=1, is_ref=0)='one',
 
//     1 => (refcount=1, is_ref=1)=...
 
//  )

// tip: unset($a) 后引用计数减一,尽管不再有某个作用域中的任何符号指向这个结构(就是变量容器),
 
// 由于数组元素"1"仍然指向数组本身,所以这个容器不能被清除
 
// 因为没有另外的符号指向它,用户没有办法清除这个结构,结果就会导致内存泄漏
 
// 庆幸的是, php将在脚本执行结束时清除这个数据结构, 但是在php清除之前,将耗费不少内存.
 
// 同样的情况也会发生在对象上,实际上对象更有可能出现这种情况,因为对象总是隐式的被引用。
 
 

(编辑:聊城站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!