實現說明
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引用數實現垃圾回收的方法,希望對大家有幫助。