PHP線程的內(nèi)存回收問題
來源:易賢網(wǎng) 閱讀:1246 次 日期:2016-08-15 14:56:10
溫馨提示:易賢網(wǎng)小編為您整理了“PHP線程的內(nèi)存回收問題”,方便廣大網(wǎng)友查閱!

當(dāng)一個(gè)PHP線程結(jié)束時(shí),當(dāng)前占用的所有內(nèi)存空間都會(huì)被銷毀。那么如果這個(gè)線程不結(jié)束,怎么回收內(nèi)存呢?

refcount:引用技術(shù)器,可以理解為指向該個(gè)容器的指針個(gè)數(shù)吧。

is_ref:是否被引用(只可能是0或者1)

賦值的流程:

<?php

$a = 'aa';

xdebug_debug_zval(a); //(refcount=1, is_ref=0),string 'aa' (length=6)

$b = $a;

//以下的兩個(gè)其實(shí)是一個(gè)變量容器

xdebug_debug_zval(a); //(refcount=2, is_ref=0),string 'aa' (length=6)

xdebug_debug_zval(b); //(refcount=2, is_ref=0),string 'aa' (length=6)

unset($b); //對(duì)變量容器 refcount 減1

xdebug_debug_zval(a); //(refcount=1, is_ref=0),string 'aa' (length=6)

xdebug_debug_zval(b); //b: no such symbol b變量被銷毀,指向被斷掉,如果對(duì)應(yīng)容器的引用技術(shù)為零,那么該塊兒內(nèi)存被回收

$b = $a;

$b = 'bb';

xdebug_debug_zval(a); //(refcount=1, is_ref=0),string 'aa' (length=6)

xdebug_debug_zval(b); //(refcount=1, is_ref=0),string 'aa' (length=6) 重新申請(qǐng)一個(gè)變量容器存儲(chǔ)b,a的變量容器引用減1

引用的流程:

<?php

$a = 'aa';

xdebug_debug_zval('a'); //(refcount=1, is_ref=0),string 'aa' (length=2)

$b = & $a;

//變量容器的引用技術(shù)加1,引用標(biāo)記置為1

xdebug_debug_zval('a'); //(refcount=2, is_ref=1),string 'aa' (length=2)

xdebug_debug_zval('b'); //(refcount=2, is_ref=1),string 'aa' (length=2)

$b = '123';

//php會(huì)發(fā)現(xiàn),該容器變量是引用(is_ref),所以容器變量不用像賦值那樣再申請(qǐng)一個(gè)

xdebug_debug_zval('a'); //(refcount=2, is_ref=1),string '123' (length=2)

xdebug_debug_zval('b'); //(refcount=2, is_ref=1),string '123' (length=2)

unset($b);

//變量容器應(yīng)用計(jì)數(shù)減1,引用為零

xdebug_debug_zval('a'); //(refcount=1, is_ref=0),string '123' (length=2)

xdebug_debug_zval('b'); // b: no such symbol

那如果多次引用,unset掉一個(gè),is_ref是否會(huì)被置為零,那樣bug不就出現(xiàn)了么?變量容器還是引用啊。那么我們來看看:

<?php

$a = 'aa';

$b = &$a;

$c = &$a;

//可以看到引用refCount是3,is_ref永遠(yuǎn)是1

xdebug_debug_zval('a'); //(refcount=3, is_ref=1),string 'aa' (length=2)

xdebug_debug_zval('b'); //(refcount=3, is_ref=1),string 'aa' (length=2)

xdebug_debug_zval('c'); //(refcount=3, is_ref=1),string 'aa' (length=2)

unset($b);

//我們期待的bug沒有出現(xiàn),只是refcount減1,is_ref還是1

xdebug_debug_zval('a'); //(refcount=2, is_ref=1),string 'aa' (length=2)

xdebug_debug_zval('b'); // b: no such symbol

xdebug_debug_zval('c'); //(refcount=2, is_ref=1),string 'aa' (length=2)

//那php它怎么知道這個(gè)容器還有引用,畢竟is_ref仍然是1,不能計(jì)數(shù),那么現(xiàn)在refcount就起作用了,是它告訴php,該變量有幾個(gè)引用,但問題又來了,如果我干點(diǎn)壞事,在引用的時(shí)候,又賦值,它會(huì)不會(huì)有bug

$e = $a;

//我們看到期望的bug還是沒出現(xiàn),這時(shí)候再賦值,就不像直接賦值那么簡(jiǎn)單refcount加1了,而是申請(qǐng)了一個(gè)新的變量容器

xdebug_debug_zval('a'); //(refcount=2, is_ref=1),string 'aa' (length=2)

xdebug_debug_zval('e'); //(refcount=1, is_ref=0),string 'aa' (length=2)

unset和賦值null都能回收變量么?很多人都錯(cuò)認(rèn)為,這兩個(gè)都能回收變量空間,其實(shí)錯(cuò)了,null只是把變量占用的空間變小了,從回收上來說,該容器依然存在。

<?php

$a = 'aa';

$b = $a;

$b = null;

//又申請(qǐng)了一個(gè)變量容器

xdebug_debug_zval('a'); //(refcount=1, is_ref=0),string 'aa' (length=2)

xdebug_debug_zval('b'); //(refcount=1, is_ref=0),null 變量空間并沒被回收

unset($b);

//這時(shí)候才釋放了b變量容器的空間

xdebug_debug_zval('a'); //(refcount=1, is_ref=0),string 'aa' (length=2)

xdebug_debug_zval('b'); //b: no such symbol

總結(jié):

1. 垃圾回收的時(shí)機(jī)

PHP中,引用計(jì)數(shù)為0,則內(nèi)存立刻釋放。也就是說,不存在環(huán)狀引用的變量,離開變量的作用域,內(nèi)存被立刻釋放。環(huán)狀引用檢測(cè)則是在滿足一定條件下觸發(fā),所以在上面的例子中,會(huì)看到使用的內(nèi)存有大幅度的波動(dòng)。也可以通過 gc_collect_cycles 函數(shù)來主動(dòng)進(jìn)行環(huán)狀引用檢測(cè)。

2. &符號(hào)的影響

顯式引用一個(gè)變量,會(huì)增加該內(nèi)存的引用計(jì)數(shù):

$a = "something";

$b = &$a;

此時(shí)unset($a), 但是仍有$b指向該內(nèi)存區(qū)域的引用,內(nèi)存不會(huì)釋放。

3. unset函數(shù)的影響

unset只是斷開一個(gè)變量到一塊內(nèi)存區(qū)域的連接,同時(shí)將該內(nèi)存區(qū)域的引用計(jì)數(shù)-1;在上面的例子中,循環(huán)體內(nèi)部,$a=new A(); unset($a);并不會(huì)將$a的引用計(jì)數(shù)減到零;

4. = null 操作的影響;

$a = null 是直接將$a 指向的數(shù)據(jù)結(jié)構(gòu)置空,同時(shí)將其引用計(jì)數(shù)歸0。

5. 腳本執(zhí)行結(jié)束的影響

腳本執(zhí)行結(jié)束,該腳本中使用的所有內(nèi)存都會(huì)被釋放,不論是否有引用環(huán)。

更多信息請(qǐng)查看網(wǎng)絡(luò)編程
易賢網(wǎng)手機(jī)網(wǎng)站地址:PHP線程的內(nèi)存回收問題
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請(qǐng)考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡(jiǎn)要咨詢 | 簡(jiǎn)要咨詢須知 | 加入群交流 | 手機(jī)站點(diǎn) | 投訴建議
工業(yè)和信息化部備案號(hào):滇ICP備2023014141號(hào)-1 云南省教育廳備案號(hào):云教ICP備0901021 滇公網(wǎng)安備53010202001879號(hào) 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號(hào)
云南網(wǎng)警備案專用圖標(biāo)
聯(lián)系電話:0871-65317125(9:00—18:00) 獲取招聘考試信息及咨詢關(guān)注公眾號(hào):hfpxwx
咨詢QQ:526150442(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報(bào)警專用圖標(biāo)