如果我有循环引用,是否可以触发PHP垃圾回收自动发生? [英] Can I trigger PHP garbage collection to happen automatically if I have circular references?

查看:368
本文介绍了如果我有循环引用,是否可以触发PHP垃圾回收自动发生?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我似乎想起了一种为类设置 __ destruct 的方法,它可以确保一旦外部对象立即清除循环引用超出范围。然而,我建立的简单测试似乎表明,这不是我预期/希望的行为。



有没有一种方法来设置我的类,以这种方式当最外层的对象超出范围时,PHP会正确地清理它们?



我不想寻找替代方法来编写这段代码,我正在寻找是否这个可以做到,如果是的话,怎么样?我一般尽可能避免使用这些类型的循环引用。

  class Bar {
private $ foo;
public function __construct($ foo){
$ this-> foo = $ foo;

public function __destruct(){
print[destroying bar] \\\
;
unset($ this-> foo);
}
}

class Foo {
private $ bar;
public function __construct(){
$ this-> bar = new Bar($ this);
}
public function __destruct(){
print[destroying foo] \\\
;
unset($ this-> bar);



函数testGarbageCollection(){
$ foo = new Foo();
}

($ i = 0; $ i <25; $ i ++){
echo memory_get_usage()。 \\\
;
testGarbageCollection();
}

输出如下所示:

  60440 
61504
62036
62564
63092
63620
[销毁foo]
[销毁条]
[销毁foo]
[销毁条]
[销毁foo]
[销毁条]
[销毁foo]
[销毁条]
[销毁foo]
[销毁条]

什么我曾希望:

  60440 
[destorying foo]
[destorying bar]
60440
[destorying foo]
[destorying bar]
60440
[destorying foo]
[destorying bar]
60440
[destorying foo ]
[destorying bar]
60440
[destorying foo]
[destorying bar]
60440
[destorying foo]
[destorying bar ]

更新:

<>有关PHP> 5.3的这个问题有几个很好的答案,但是我选择了适用于PHP的答案5.3,因为它实际上与我的项目(PHP 5.2.x)有关。

解决方案 只在对象被回收后才被调用,所以你不能使用它。虽然你可以创建一个手动清理功能:

  class Foo {
private $ bar;
public function __construct(){
$ this-> bar = new Bar($ this);

public function cleanup(){
$ this-> bar = null;
}
public function __destruct(){
print[destroying foo] \\\
;
}
}

class Bar {
private $ foo;
public function __construct($ foo){
$ this-> foo = $ foo;

public function __destruct(){
print[destroying bar] \\\
;



函数testGarbageCollection(){
$ foo = new Foo();
$ foo-> cleanup();
}

我不确定这是多么有用,但这是您唯一的选择< 5.3

I seem to recall a way to setup the __destruct for a class in such a way that it would ensure that circular references would be cleaned up as soon as the outside object falls out of scope. However, the simple test I built seems to indicate that this is not behaving as I had expected/hoped.

Is there a way to setup my classes in such a way that PHP would clean them up correctly when the outermost object falls out of scope?

I am not looking for alternate ways to write this code, I am looking for whether or not this can be done, and if so, how? I generally try to avoid these types of circular references where possible.

class Bar {
    private $foo;
    public function __construct($foo) {
        $this->foo = $foo;
    }
    public function __destruct() {
        print "[destroying bar]\n";
        unset($this->foo);
    }
}

class Foo {
    private $bar;
    public function __construct() {
        $this->bar = new Bar($this);
    }
    public function __destruct() {
        print "[destroying foo]\n";
        unset($this->bar);
    }
}

function testGarbageCollection() {
    $foo = new Foo();
}

for ( $i = 0; $i < 25; $i++ ) {
    echo memory_get_usage() . "\n";
    testGarbageCollection();
}

The output looks like this:

60440
61504
62036
62564
63092
63620
 [ destroying foo ]
 [ destroying bar ]
 [ destroying foo ]
 [ destroying bar ]
 [ destroying foo ]
 [ destroying bar ]
 [ destroying foo ]
 [ destroying bar ]
 [ destroying foo ]
 [ destroying bar ]

What I had hoped for:

60440
 [ destorying foo ]
 [ destorying bar ]
60440
 [ destorying foo ]
 [ destorying bar ]
60440
 [ destorying foo ]
 [ destorying bar ]
60440
 [ destorying foo ]
 [ destorying bar ]
60440
 [ destorying foo ]
 [ destorying bar ]
60440
 [ destorying foo ]
 [ destorying bar ]

UPDATE:

There are several great answers to this question relating to PHP > 5.3, but I selected the answer that would work with PHP < 5.3 since it actually relates to my project ( PHP 5.2.x ).

解决方案

As __destruct is only called once the object is being reclaimed, you can't use it for that. You can create a manual cleanup function though:

class Foo {
  private $bar;
  public function __construct() {
    $this->bar = new Bar($this);
  }
  public function cleanup() {
    $this->bar = null;
  }
  public function __destruct() {
    print "[destroying foo]\n";
  }
}

class Bar {
  private $foo;
  public function __construct($foo) {
    $this->foo = $foo;
  }
  public function __destruct() {
    print "[destroying bar]\n";
  }
}

function testGarbageCollection() {
  $foo = new Foo();
  $foo->cleanup();
}

I'm not sure how useful this is, but that's really your only option < 5.3

这篇关于如果我有循环引用,是否可以触发PHP垃圾回收自动发生?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆