亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

目錄
關(guān)于循環(huán)引用
循環(huán)引用的典型示例
使用弱引用防止循環(huán)引用
閉包和循環(huán)引用
閉包中對$this的引用
生成器和循環(huán)引用
結(jié)論
閱讀更多
首頁 后端開發(fā) php教程 PHP 閉包和生成器可以保存循環(huán)引用

PHP 閉包和生成器可以保存循環(huán)引用

Jan 18, 2025 am 06:03 AM

PHP Closures and Generators can hold circular references

PHP中的循環(huán)引用是內(nèi)存泄漏的常見原因。當對象直接或間接地相互引用時,就會發(fā)生循環(huán)引用。幸運的是,PHP有一個垃圾收集器可以檢測和清理循環(huán)引用。但是,這會消耗CPU周期并可能減慢應(yīng)用程序的速度。

垃圾收集器會在內(nèi)存中存在10,000個可能的循環(huán)對象或數(shù)組,并且其中一個超出作用域時觸發(fā)。

如果您有少量使用大量內(nèi)存的對象,則永遠不會觸發(fā)垃圾收集。即使內(nèi)存被垃圾收集器應(yīng)該收集的孤立對象使用,您也可能達到內(nèi)存限制。

這就是為什么您應(yīng)該識別創(chuàng)建循環(huán)引用的情況并避免它們的原因。

理想情況下,對于Web應(yīng)用程序,您希望禁用垃圾收集器,并在發(fā)送響應(yīng)后讓PHP釋放所有內(nèi)存。但這對于長時間運行的腳本(例如守護進程或工作進程)來說是危險的,因為內(nèi)存泄漏會隨著時間的推移而累積,并通過頻繁調(diào)用垃圾收集器來減慢應(yīng)用程序的速度。

在本文中,我們將探討閉包和生成器如何保存循環(huán)引用以及如何防止它們。

  • 關(guān)于循環(huán)引用
    • 循環(huán)引用的典型示例
    • 使用弱引用防止循環(huán)引用
  • 閉包和循環(huán)引用
  • 生成器和循環(huán)引用
  • 結(jié)論

關(guān)于循環(huán)引用

循環(huán)引用的典型示例

class A {
    public B $b;

    public function __construct()
    {
        $this->b = new B($this);
    }
}

class B {
    public function __construct(public A $a) {}
}

在此示例中,A和B相互引用。當您創(chuàng)建A的實例時,它會創(chuàng)建一個引用A的B實例。這會創(chuàng)建一個循環(huán)引用。

為了檢測循環(huán)引用,我們可以使用gc_collect_cycles()手動觸發(fā)垃圾收集器,并使用gc_status()讀取收集到的引用的數(shù)量。

// 創(chuàng)建的對象但未分配給變量
new A();

gc_collect_cycles();
print_r(gc_status());

這將輸出:

<code>Array
(
    ...
    [collected] => 2
    ...
)</code>

此示例表明垃圾收集器已檢測到并刪除了2個具有循環(huán)引用的對象。

您還可以使用xdebug_debug_zval()函數(shù)查看對象的引用數(shù)量。

使用弱引用防止循環(huán)引用

當遇到循環(huán)引用時,一個簡單的解決方案是使用弱引用。弱引用是一個對象,它持有的引用不會阻止垃圾收集器收集它引用的對象。在PHP中,您可以使用WeakReference類創(chuàng)建弱引用。

這需要對代碼進行一些更改。B類現(xiàn)在存儲WeakReference對象而不是A對象。您必須使用WeakReference對象的get()方法訪問A對象。

class A {
    public B $b;

    public function __construct()
    {
        $this->b = new B($this);
    }
}

class B {
    /** @var WeakReference<a> $a */
    public WeakReference $a;

    public function __construct(A $a)
    {
        $this->a = WeakReference::create($a);    
    }
}
// 創(chuàng)建的對象但未分配給變量
new A();

gc_collect_cycles();
print_r(gc_status());
// [collected] => 0

在輸出中,您將看到收集到的引用數(shù)量現(xiàn)在為0。

提示1:僅在必要時使用弱引用來防止循環(huán)引用。

閉包和循環(huán)引用

PHP中閉包的概念是創(chuàng)建一個可以訪問父作用域中變量的函數(shù)。如果您不小心,這可能會導致循環(huán)引用。

class A {
    public B $b;

    public function __construct()
    {
        $this->b = new B($this);
    }
}

class B {
    public function __construct(public A $a) {}
}

在此示例中,閉包$a->b引用父作用域中的變量$a。循環(huán)引用很容易發(fā)現(xiàn),因為引用是明確的。

但是,如果您使用閉包的簡寫語法,則可能會以更隱蔽的方式出現(xiàn)相同的問題。使用箭頭函數(shù),變量$a不會在閉包中顯式引用,但它仍然被按引用捕獲。

// 創(chuàng)建的對象但未分配給變量
new A();

gc_collect_cycles();
print_r(gc_status());

在此示例中,收集到的引用數(shù)量為2,表明存在循環(huán)引用。

閉包中對$this的引用

在類方法中創(chuàng)建的任何非靜態(tài)閉包都將對對象實例($this)具有引用,即使沒有訪問$this也是如此。

<code>Array
(
    ...
    [collected] => 2
    ...
)</code>

這是因為$this引用始終在閉包中按引用捕獲??梢允褂?code>Reflection::getClosureThis()訪問它。

class A {
    public B $b;

    public function __construct()
    {
        $this->b = new B($this);
    }
}

class B {
    /** @var WeakReference<a> $a */
    public WeakReference $a;

    public function __construct(A $a)
    {
        $this->a = WeakReference::create($a);    
    }
}

如果從全局作用域或靜態(tài)方法中創(chuàng)建閉包,則$this引用為null。

提示2:如果您不需要$this,則始終使用static function () {}static fn () =>來創(chuàng)建閉包。

生成器和循環(huán)引用

我們來說說這篇文章的原因。我最近發(fā)現(xiàn)了一些東西: 生成器會保留引用,只要它們沒有被耗盡。

在此示例中,該類將生成器存儲在一個屬性中,但生成器對對象實例具有$this引用。 生成器表現(xiàn)得像一個閉包,并保留對對象實例的引用。

// 創(chuàng)建的對象但未分配給變量
new A();

gc_collect_cycles();
print_r(gc_status());
// [collected] => 0

類實例被垃圾收集器收集,因為它對生成器有引用,而生成器對對象實例有引用。

一旦生成器被耗盡,引用就會被釋放,對象實例就會從內(nèi)存中刪除。

function createCircularReference()
{
    $a = new stdClass();
    $a->b = function () use ($a) {
        return $a;
    };

    return $a;
}

提示3:通過迭代始終耗盡生成器。

提示4:使用靜態(tài)方法或閉包來創(chuàng)建生成器,以免保留對對象實例的引用。

結(jié)論

循環(huán)引用是PHP中內(nèi)存泄漏的常見原因。即使垃圾收集器可以檢測和清理循環(huán)引用,它也會消耗CPU周期并可能減慢應(yīng)用程序的速度。您必須檢測創(chuàng)建此類循環(huán)引用的情況并調(diào)整代碼以防止它們。使用弱引用可以防止循環(huán)引用,但一些簡單的技巧可以幫助您首先防止循環(huán)引用:

  • 如果不需要$this,則使用static function () {}static fn () =>來創(chuàng)建閉包。
  • 通過迭代始終耗盡生成器。
  • 使用靜態(tài)方法或閉包來創(chuàng)建生成器,以免保留對對象實例的引用。

閱讀更多

  • PHP垃圾收集——性能注意事項
  • PHP中的垃圾收集是什么?如何充分利用它?
  • memprof——PHP的內(nèi)存分析器。幫助查找PHP腳本中的內(nèi)存泄漏。
  • Xdebug的內(nèi)置分析器

以上是PHP 閉包和生成器可以保存循環(huán)引用的詳細內(nèi)容。更多信息請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本站聲明
本文內(nèi)容由網(wǎng)友自發(fā)貢獻,版權(quán)歸原作者所有,本站不承擔相應(yīng)法律責任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請聯(lián)系admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費脫衣服圖片

Undresser.AI Undress

Undresser.AI Undress

人工智能驅(qū)動的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用于從照片中去除衣服的在線人工智能工具。

Clothoff.io

Clothoff.io

AI脫衣機

Video Face Swap

Video Face Swap

使用我們完全免費的人工智能換臉工具輕松在任何視頻中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的代碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

功能強大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級代碼編輯軟件(SublimeText3)

PHP變量范圍解釋了 PHP變量范圍解釋了 Jul 17, 2025 am 04:16 AM

PHP變量作用域常見問題及解決方法包括:1.函數(shù)內(nèi)部無法訪問全局變量,需使用global關(guān)鍵字或參數(shù)傳入;2.靜態(tài)變量用static聲明,只初始化一次并在多次調(diào)用間保持值;3.超全局變量如$_GET、$_POST可在任何作用域直接使用,但需注意安全過濾;4.匿名函數(shù)需通過use關(guān)鍵字引入父作用域變量,修改外部變量則需傳遞引用。掌握這些規(guī)則有助于避免錯誤并提升代碼穩(wěn)定性。

如何在PHP中牢固地處理文件上傳? 如何在PHP中牢固地處理文件上傳? Jul 08, 2025 am 02:37 AM

要安全處理PHP文件上傳需驗證來源與類型、控制文件名與路徑、設(shè)置服務(wù)器限制并二次處理媒體文件。1.驗證上傳來源通過token防止CSRF并通過finfo_file檢測真實MIME類型使用白名單控制;2.重命名文件為隨機字符串并根據(jù)檢測類型決定擴展名存儲至非Web目錄;3.PHP配置限制上傳大小及臨時目錄Nginx/Apache禁止訪問上傳目錄;4.GD庫重新保存圖片清除潛在惡意數(shù)據(jù)。

在PHP中評論代碼 在PHP中評論代碼 Jul 18, 2025 am 04:57 AM

PHP注釋代碼常用方法有三種:1.單行注釋用//或#屏蔽一行代碼,推薦使用//;2.多行注釋用/.../包裹代碼塊,不可嵌套但可跨行;3.組合技巧注釋如用/if(){}/控制邏輯塊,或配合編輯器快捷鍵提升效率,使用時需注意閉合符號和避免嵌套。

發(fā)電機如何在PHP中工作? 發(fā)電機如何在PHP中工作? Jul 11, 2025 am 03:12 AM

AgeneratorinPHPisamemory-efficientwaytoiterateoverlargedatasetsbyyieldingvaluesoneatatimeinsteadofreturningthemallatonce.1.Generatorsusetheyieldkeywordtoproducevaluesondemand,reducingmemoryusage.2.Theyareusefulforhandlingbigloops,readinglargefiles,or

撰寫PHP評論的提示 撰寫PHP評論的提示 Jul 18, 2025 am 04:51 AM

寫好PHP注釋的關(guān)鍵在于明確目的與規(guī)范,注釋應(yīng)解釋“為什么”而非“做了什么”,避免冗余或過于簡單。1.使用統(tǒng)一格式,如docblock(/*/)用于類、方法說明,提升可讀性與工具兼容性;2.強調(diào)邏輯背后的原因,如說明為何需手動輸出JS跳轉(zhuǎn);3.在復雜代碼前添加總覽性說明,分步驟描述流程,幫助理解整體思路;4.合理使用TODO和FIXME標記待辦事項與問題,便于后續(xù)追蹤與協(xié)作。好的注釋能降低溝通成本,提升代碼維護效率。

快速PHP安裝教程 快速PHP安裝教程 Jul 18, 2025 am 04:52 AM

ToinstallPHPquickly,useXAMPPonWindowsorHomebrewonmacOS.1.OnWindows,downloadandinstallXAMPP,selectcomponents,startApache,andplacefilesinhtdocs.2.Alternatively,manuallyinstallPHPfromphp.netandsetupaserverlikeApache.3.OnmacOS,installHomebrew,thenrun'bre

學習PHP:初學者指南 學習PHP:初學者指南 Jul 18, 2025 am 04:54 AM

易于效率,啟動啟動tingupalocalserverenverenvirestoolslikexamppandacodeeditorlikevscode.1)installxamppforapache,mysql,andphp.2)uscodeeditorforsyntaxssupport.3)

如何通過php中的索引訪問字符串中的字符 如何通過php中的索引訪問字符串中的字符 Jul 12, 2025 am 03:15 AM

在PHP中獲取字符串特定索引字符可用方括號或花括號,但推薦方括號;索引從0開始,超出范圍訪問返回空值,不可賦值;處理多字節(jié)字符需用mb_substr。例如:$str="hello";echo$str[0];輸出h;而中文等字符需用mb_substr($str,1,1)獲取正確結(jié)果;實際應(yīng)用中循環(huán)訪問前應(yīng)檢查字符串長度,動態(tài)字符串需驗證有效性,多語言項目建議統(tǒng)一使用多字節(jié)安全函數(shù)。

See all articles