• 技术文章 >PHP >PHP教程

    php引用计数如何实现垃圾回收

    小妮浅浅小妮浅浅2021-08-17 10:02:33原创4592

    实现说明

    1、给对象添加引用计数器,每次在某个地方引用计数器的值都会增加。每当引用失效时,计数器的值就会减一。

    变量value的refcount减一后等于0的话,这个value就会被释放,不是垃圾。垃圾回收器不处理。

    变量value的refcount减一后大于0以上的话,这个value被认为不能释放,有可能成为垃圾。

    2、垃圾回收器收集可能的垃圾,达到一定数量后启动垃圾鉴定程序,释放真正的垃圾。

    实例

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    70

    71

    72

    73

    74

    75

    76

    77

    78

    79

    80

    81

    82

    83

    84

    85

    86

    87

    88

    89

    90

    91

    92

    93

    94

    95

    96

    97

    98

    <?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清除之前,将耗费不少内存.

    // 同样的情况也会发生在对象上,实际上对象更有可能出现这种情况,因为对象总是隐式的被引用。

    以上就是php引用计数实现垃圾回收的方法,希望对大家有所帮助。更多php学习指路:php教程

    推荐操作系统:windows7系统、PHP5.6、DELL G3电脑

    专题推荐:php引用计数 垃圾回收
    上一篇:PHP中Zval是什么 下一篇:php中TCP和UDP的区别

    相关文章推荐

    • php有哪些文件包含漏洞• php不能生成图片的解决办法• php正则替换函数的整理• php中n阶乘的实现方法• php rtrim()函数删除字符• PHP有哪些屏蔽错误的方法• php字符串的截取方式• PHP内部函数是什么• PHP中strval()函数如何使用• PHP核心架构是什么• PHP中hash table有哪些特点• PHP中Zval是什么

    全部评论我要评论

    © 2021 Python学习网 苏ICP备2021003149号-1

  • 取消发布评论
  • 

    Python学习网