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

目錄
關(guān)於循環(huán)引用
循環(huán)引用的典型範(fàn)例
使用弱引用防止循環(huán)引用
閉包與循環(huán)引用
閉包中對(duì)$this的引用
產(chǎn)生器與循環(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)引用是記憶體洩漏的常見原因。當(dāng)物件直接或間接地相互引用時(shí),就會(huì)發(fā)生循環(huán)引用。幸運(yùn)的是,PHP有一個(gè)垃圾收集器可以偵測和清理循環(huán)引用。但是,這會(huì)消耗CPU週期並可能減慢應(yīng)用程式的速度。

垃圾收集器會(huì)在記憶體中存在10,000個(gè)可能的循環(huán)物件或陣列,並且其中一個(gè)超出作用域時(shí)觸發(fā)。

如果您有少量使用大量記憶體的對(duì)象,則永遠(yuǎn)不會(huì)觸發(fā)垃圾收集。即使記憶體被垃圾收集器應(yīng)該收集的孤立物件使用,您也可能達(dá)到記憶體限制。

這就是為什麼您應(yīng)該識(shí)別建立循環(huán)引用的情況並避免它們的原因。

理想情況下,對(duì)於Web應(yīng)用程序,您希望停用垃圾收集器,並在發(fā)送回應(yīng)後讓PHP釋放所有記憶體。但這對(duì)於長時(shí)間運(yùn)行的腳本(例如守護(hù)進(jìn)程或工作進(jìn)程)來說是危險(xiǎn)的,因?yàn)橛洃涹w洩漏會(huì)隨著時(shí)間的推移而累積,並透過頻繁調(diào)用垃圾收集器來減慢應(yīng)用程式的速度。

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

  • 關(guān)於循環(huán)引用
    • 循環(huán)引用的典型範(fàn)例
    • 使用弱引用防止循環(huán)引用
  • 閉包與循環(huán)引用
  • 產(chǎn)生器與循環(huán)引用
  • 結(jié)論

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

循環(huán)引用的典型範(fàn)例

class A {
    public B $b;

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

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

在此範(fàn)例中,A和B相互引用。當(dāng)您建立A的實(shí)例時(shí),它會(huì)建立一個(gè)引用A的B實(shí)例。這會(huì)建立一個(gè)循環(huán)引用。

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

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

gc_collect_cycles();
print_r(gc_status());

這將輸出:

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

此範(fàn)例顯示垃圾收集器已偵測到並刪除了2個(gè)具有循環(huán)引用的物件。

您也可以使用xdebug_debug_zval()函數(shù)查看物件的參考數(shù)量。

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

當(dāng)遇到循環(huán)引用時(shí),一個(gè)簡單的解決方案是使用弱引用。弱引用是一個(gè)對(duì)象,它所持有的引用不會(huì)阻止垃圾收集器收集它所引用的對(duì)象。在PHP中,您可以使用WeakReference類別建立弱引用。

這需要對(duì)程式碼進(jìn)行一些更改。 B類現(xiàn)在儲(chǔ)存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)建的對(duì)象但未分配給變量
new A();

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

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

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

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

PHP中閉包的概念是建立一個(gè)可以存取父作用域中變數(shù)的函數(shù)。如果您不小心,這可能會(huì)導(dǎo)致循環(huán)引用。

class A {
    public B $b;

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

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

在此範(fàn)例中,閉包$a->b引用父作用域中的變數(shù)$a。循環(huán)引用很容易發(fā)現(xiàn),因?yàn)橐檬敲鞔_的。

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

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

gc_collect_cycles();
print_r(gc_status());

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

閉包中對(duì)$this的引用

在類別方法中建立的任何非靜態(tài)閉包都會(huì)對(duì)物件實(shí)例($this)具有引用,即使沒有存取$this也是如此。

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

這是因?yàn)?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)方法建立閉包,則$this引用為null。

提示2:如果您不需要$this,請(qǐng)務(wù)必使用static function () {}static fn () =>來建立閉包。

產(chǎn)生器與循環(huán)引用

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

在此範(fàn)例中,該類別將生成器儲(chǔ)存在一個(gè)屬性中,但生成器對(duì)物件實(shí)例具有$this引用。 生成器表現(xiàn)得像一個(gè)閉包,並保留對(duì)物件實(shí)例的參考。

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

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

類別實(shí)例被垃圾收集器收集,因?yàn)樗鼘?duì)生成器有引用,而生成器對(duì)物件實(shí)例有引用。

一旦生成器被耗盡,參考就會(huì)被釋放,物件實(shí)例就會(huì)從記憶體中刪除。

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

    return $a;
}

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

提示4:使用靜態(tài)方法或閉包來建立生成器,以免保留物件實(shí)例的參考。

結(jié)論

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

  • 如果不需要$this,則使用static function () {}static fn () =>來建立閉包。
  • 透過迭代始終耗盡生成器。
  • 使用靜態(tài)方法或閉包來建立生成器,以免保留物件實(shí)例的參考。

閱讀更多

  • PHP垃圾收集-效能注意事項(xiàng)
  • PHP中的垃圾收集是什麼?如何充分利用它?
  • memprof——PHP的記憶體分析器。協(xié)助查找PHP腳本中的記憶體洩漏。
  • Xdebug的內(nèi)建分析器

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

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願(yuàn)投稿,版權(quán)歸原作者所有。本站不承擔(dān)相應(yīng)的法律責(zé)任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請(qǐng)聯(lián)絡(luò)admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強(qiáng)大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

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

SublimeText3 Mac版

SublimeText3 Mac版

神級(jí)程式碼編輯軟體(SublimeText3)

PHP變量範(fàn)圍解釋了 PHP變量範(fàn)圍解釋了 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ī)則有助於避免錯(cuò)誤並提升代碼穩(wěn)定性。

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

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

在PHP中評(píng)論代碼 在PHP中評(píng)論代碼 Jul 18, 2025 am 04:57 AM

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

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

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

撰寫PHP評(píng)論的提示 撰寫PHP評(píng)論的提示 Jul 18, 2025 am 04:51 AM

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

快速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 12, 2025 am 03:15 AM

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

學(xué)習(xí)PHP:初學(xué)者指南 學(xué)習(xí)PHP:初學(xué)者指南 Jul 18, 2025 am 04:54 AM

易於效率,啟動(dòng)啟動(dòng)tingupalocalserverenverenvirestoolslikexamppandacodeeditorlikevscode.1)installxamppforapache,mysql,andphp.2)uscodeeditorforsyntaxssupport.3)

See all articles