不想传火的,可以点击下面的链接!
给我点赞嘛,球球了!

What This?
现象
引用计数法是一种垃圾回收算法,用于跟踪对象被引用的次数。在该算法中,每个对象都会维护一个计数器,记录有多少个指针指向它。
当一个新指针引用一个对象时,该对象的计数器就会加1,当指针被释放时,对象的计数器就会减1。
当对象的计数器变为0时,说明该对象没有任何指针指向它,也就意味着该对象可以被回收。
引用计数法会定期扫描内存中的对象,并回收计数器为0的对象。
优缺点
- 优点(快):引用计数法的优点是回收垃圾的时机可以很快,因为对象的计数器是在实时更新的。
- 缺点(循环引用):是如果存在循环引用,即两个或多个对象互相引用,但是没有其他对象引用它们,那么这些对象的计数器永远不会变为0,也就无法回收它们,会导致内存泄漏。
因此,引用计数法通常需要与其他垃圾回收算法一起使用,以解决循环引用的问题。
举例
肯定有人没耐心看文字!不过谁叫我人心善呢,见不得你们这么痛苦。

计数器的构成其实很简单,就是只有计数器和域,
- 域:专门存放自身节点与其他节点的引用关系,即
自己的指针->其他节点 - 计数器:统计被引用的次数

下面的两幅图就很形象了。
一开始我们创建了ABCD这四个节点,其中C被A引用

然后修改A->C变成A->B之后的结果如下;

你学废了吗?
实现
伪代码
update_ptr() 函数:用于更新指针 ptr,使其指向对象 obj,同时进行计数器值的增减。
注意:
这里的ptr有两重含义,意思就是如上图的修改
A->C变成A->B涉及到的两个不同的指针。
另外要保证先增加后减少,这样就可以避免ptr和obj是同一个对象的情况所导致的被误删。

inc_ref_cnt() 函数:计数器增量操作。

dec_ref_cnt()函数:计数器减量操作。

GO实现
目录结构:
ReferenceCount
| |
| main.go
|
----->PKG
|
------>allocate.go
------>createData.go
------>freeLinkedList.go
------>object.go
链表freeLinkedList.go
定义了一个 FreeLinkedList 的数据结构,它是一个基于链表的数据结构,其中的节点被定义为 Node 结构体。链表的头节点是一个指向第一个节点的指针。
Node 结构体包含了一个 data 属性,用于存储节点的数据值,以及一个 next 属性,指向下一个节点。String() 方法实现了将节点的数据值格式化输出的功能。
type Node struct {
data interface{
}
next *Node
}
type FreeLinkedList struct {
head *Node
}
这个 FreeLinkedList 数据结构提供了以下几个方法:
insertAtEnd:在链表的末尾插入一个新的节点,新节点的数据值是传入的参数。
func (list *FreeLinkedList) insertAtEnd(data interface{
}) {
newNode := &Node{
data: data}
if list.head == nil {
list.head = newNode
} else {
current := list.head
for current.next != nil {
current = current.next
}
current.next = newNode
}
}
deleteNode:删除链表中的一个节点,被删除节点的数据值是传入的参数。
func (list *FreeLinkedList) deleteNode(data interface{
}) {
if list.head == nil {
return
}
if list.head.data == data {
list.head = list.head.next
return
}
prev := list.head
current := list.head.next
for current != nil {
if current.data == data {
prev.next = current.next
return
}
prev = current
current = current.next
}
}
printLinkedList:打印整个链表,从头节点开始依次输出每个节点的数据值。
func (n *Node) String() string {
return fmt.Sprintf("%v", n.data)
}
func (list

文章详细介绍了引用计数法的原理,包括其优点和缺点,特别是对于循环引用的问题。通过一个Go语言实现的例子,展示了如何使用引用计数法管理内存,包括对象的引用更新、计数器的增减以及对象的回收。此外,还涉及到了内存分配和回收的机制,以及如何处理空闲链表来减少内存碎片。
最低0.47元/天 解锁文章
1092






