引用计数 GC

    这两天看PHP官方文档时,有对垃圾回收的相关描述。PHP的GC采用引用计数机制,在 5.3.0 版本之后使用文章 Concurrent Cycle Collection in Reference Counted Systems  中的同步算法。相较php之前使用的引用计数算法,该算法解决了对象的循环引用导致的内存不能回收问题。

    文章对算法的描述比较清楚,其中有伪代码及其描述,大致分两部分:

1 对对象计数的增减,使用 Increment() 和 Decrement():

 1 Increment(S)
 2     RC(S) = RC(S) + 1
 3     color(S) = black
 4 
 5 Decrement(S)
 6     RC(S) = RC(S) - 1
 7     if (RC(S) == 0)
 8         Release(S)
 9     else
10         PossibleRoot(S)
11 
12 Release(S)
13     for T in children(S)
14         Decrement(T)
15     color(S) = black
16     if (! buffered(S))
17         Free(S)
18 
19 PossibleRoot(S)
20     if (color(S) != purple)
21         color(S) = purple
22         if (! buffered(S))
23             buffered(S) = true
24             append S to Roots

2 对无用对象内存的收集释放(包括循环应用对象) CollectCycles():

 1 CollectCycles()
 2     MarkRoots()
 3     ScanRoots()
 4     CollectRoots()
 5 
 6 MarkRoots()
 7     for S in Roots
 8         if (color(S) == purple)
 9             MarkGray(S)
10         else
11             buffered(S) = false
12             remove S from Roots
13             if (color(S) == black and RC(S) == 0)
14                 Free(S)
15 
16 ScanRoots()
17     for S in Roots
18         Scan(S)
19 
20 CollectRoots()
21     for S in Roots
22         remove S from Roots
23         buffered(S) = false
24         CollectWhite(S)
25 
26 MarkGray(S)
27     if (color(S) != gray)
28         color(S) = gray
29         for T in children(S)
30             RC(T) = RC(T) - 1
31             MarkGray(T)
32 
33 Scan(S)
34     if (color(S) == gray)
35         if (RC(S) > 0)
36             ScanBlack(S)
37         else
38             color(S) = white
39             for T in children(S)
40                 Scan(T)
41 
42 ScanBlack(S)
43     color(S) = black
44     for T in children(S)
45         RC(T) = RC(T) + 1
46         if (color(T) != black)
47             ScanBlack(T)
48 
49 CollectWhite(S)
50     if (color(S) == white and ! buffered(S))
51         color(S) = black
52         for T in children(S)
53             CollectWhite(T)
54         Free(S)

其中有一点,在 MarkGray 的时候将所有引用计数减一,这时候针对同一对象的多个引用计数都会减一,所以如果只有有循环引用(没有其它引用)的对象的引用数会减到 <= 0(这里不太确定是不是会小于零),这个时候便可清除该对象。

猜你喜欢

转载自www.cnblogs.com/sun-shy/p/12420864.html
今日推荐