
實現說明
1.給物件添加引用計數器,每次在某個地方引用計數器的值都會增加。每當引用失效時,計數器的值就會減一。
變數value的refcount減一後等於0的話,這個value就會被釋放,不是垃圾。垃圾回收器不處理。
變數value的refcount減一後大於0以上的話,這個value被認為不能釋放,有可能變成垃圾。
2.垃圾回收器收集可能的垃圾,達到一定數量後啟動垃圾鑑定程序,釋放真正的垃圾。
實例
<?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(
'名' => '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, 是_ref=1)=array (
// 0 => (refcount=1, is_ref=0)='one',
// 1 => (refcount=1, is_ref=1)=...
// )
// tip: unset($a) 後引用計數減一,儘管不再有某個作用域中的任何符號指向這個結構(就是變數容器),
// 由於數組元素"1"仍然指向數組本身,所以這個容器不能被清除// 因為沒有另外的符號指向它,用戶沒有辦法清除這個結構,結果就會導致內存洩漏// 慶幸的是, php將在腳本執行結束時清除這個資料結構, 但是在php清除之前,將耗費不少內存.
// 同樣的情況也會發生在物件上,實際上物件更有可能出現這種情況,因為物件總是隱式的被引用。以上就是php引用數實現垃圾回收的方法,希望對大家有幫助。