计数对应拥有关系
引用计数不是统计程序中所有看起来像地址的数值,而是维护规定的拥有关系。CPython 的接口区分借用引用和强引用;取得新的强引用后,调用方承担日后释放它的责任。
对普通可销毁对象,最后一个强引用释放会触发类型的释放函数。释放还可能运行用户代码,因此扩展模块应先让共享状态保持一致,再执行可能销毁对象的操作。
参考:[1]
为什么环不会自行归零
设对象甲强引用乙,乙也强引用甲。即使外部拥有者都已离开,两个内部引用仍能让计数保持非零,单纯等待计数归零就无法回收这一组对象。
Rust 的 Rc 采用非原子计数,适用于单线程共享拥有;多线程共享有单独的 Arc 类型。使用 Weak 表示反向或观察关系,可以避免让每条边都成为维持对象存活的强引用。
原子计数保护的是共享拥有关系,不会自动让被拥有的数据也支持任意并发修改。Rust的Arc<T>只有在T满足相应Send与Sync条件时,才具备对应跨线程能力;把RefCell放进Arc,也不会把RefCell的非线程安全借用计数变成安全的。需要共享可变内容时,常见设计是Arc<Mutex<T>>等组合,由另一层机制负责访问同步。这把“多少拥有者维持存活”与“多个线程怎样访问内容”分成了两个问题。
弱引用与辅助回收
弱引用需要在使用前确认目标仍存在,不能把它当成永远有效的普通拥有指针。树结构可以让父节点强引用孩子、孩子弱引用父节点,但设计仍须与真实生命周期相符。
引用计数也能与其他回收机制并用。CPython 的循环垃圾回收器补充其引用计数,处理无法仅靠计数发现的引用环;这不意味着所有使用引用计数的系统都自动拥有循环回收器。