代码之家  ›  专栏  ›  技术社区  ›  Michal Czardybon

弱引用是如何实现的?

  •  16
  • Michal Czardybon  · 技术社区  · 17 年前

    我想知道弱引用是如何在内部工作的,例如在.NET或Java中。我的两个基本想法是:

    1. “侵入式”-将弱引用列表添加到最顶级的类(对象类)。然后,当一个对象被销毁时,所有弱引用都可以迭代并设置为空。
    2. “非侵入性”—维护对象指向弱引用列表的指针的哈希表。当对对象B创建弱引用A时,哈希表中会有一个修改或创建的条目,其键将是指向B的指针。
    3. “脏”—存储每个对象的特殊哈希值,当对象被破坏时,哈希值将归零。弱引用将复制该哈希值,并将其与对象的值进行比较,以检查对象是否活动。但是,当直接使用时,这会导致访问冲突错误,因此我认为需要一个具有该哈希值的额外对象。

    这些解决方案中的任何一个似乎都是干净的,也不是有效的。有人知道这是怎么做的吗?

    5 回复  |  直到 12 年前
        1
  •  5
  •   pgras    17 年前

    不确定我理解了你的问题,但是你可以看看Java中的类弱引用及其超类引用的实现。它有很好的注释,您可以看到它有一个由GC专门处理的字段,另一个字段由VM直接使用。

        2
  •  6
  •   Marc Gravell    17 年前

    在.NET中,当 WeakReference 创建后,将要求GC提供一个表示引用的句柄/不透明标记。然后,当需要时, 弱引用 使用此句柄询问GC该句柄是否仍然有效(即原始对象仍然存在),如果仍然有效,则可以获取实际的对象引用。

    因此,这是针对对象地址构建一个令牌/句柄列表(并可能在碎片整理等过程中维护该列表)。

    我不确定我100%理解这三颗子弹,所以我不知道哪颗(如果有的话)是最接近的。

        3
  •  3
  •   pfalcon    12 年前

    弱引用的实现在业界似乎是保密的;-)。例如,到目前为止, wikipedia article 缺少任何实现细节。看看上面的答案(包括接受的答案):“去看看来源”或“我想”;—\。

    在所有的答案中,只有一个引用了python的pep 205是有洞察力的。正如它所说,对于任何一个对象,如果我们把weakref看作一个实体本身,那么最多只能有一个弱引用。

    其余部分描述了松鼠语言的实现。所以,weakref本身就是一个对象,当你把弱引用放到某个容器中的对象时,你实际上把引用放到weakref对象中。每个ref countable对象都有一个字段来存储指向其weakerf的指针,在实际请求weakerf之前,该字段为空。每个对象都有方法来请求weakerf,它要么从字段返回现有(singleton)weakerf,要么创建它并在字段中缓存。

    当然,Weakref指向了原始的物体。因此,您只需浏览所有处理对象引用的可用位置,并添加对weakerefs的透明处理(即自动取消引用)。(“透明的”替代方法是添加虚拟的“访问”方法,该方法将是大多数对象的标识,并实际取消对weakref的引用。)

    当对象有指向其weakerf的指针时,对象就可以在自己的析构函数中使weakerf无效。

    这个实现非常干净(没有“调用GC”之类的魔力),并且有O(1)运行时成本。当然,这是非常贪婪的内存——需要向每个对象添加+1指针字段,即使通常90%以上的对象为空。当然,vhls对于每个对象已经有很大的内存开销,并且可能有机会压缩不同的“额外”字段。例如,对象类型通常是一个小的枚举,因此可以将类型和某种weakerf引用合并到单个机器字中(例如,将weakerf对象保留在单独的区域中,并使用索引)。

        4
  •  2
  •   Josh Lee ZZ Coder    17 年前

    蟒蛇 PEP 205 对弱引用在Python中的行为有一个很好的解释,这让我们对如何实现它们有了一些了解。因为弱引用是不可变的,所以每个对象只能有一个,您可以根据需要将引用传递给它。因此,当对象被破坏时,只需要一个弱引用无效。

        5
  •  0
  •   supercat    14 年前

    我认为,通常的方法是系统维护一些弱引用列表。当垃圾收集器执行时,在删除死对象之前,系统将遍历弱引用列表,并使目标未被标记为活动的任何引用无效。根据系统的不同,这可能发生在系统临时恢复符合立即完成条件的对象之前或之后(对于.NET,有两种 WeakReference --其中一个在系统扫描终结器之前被有效地处理,这意味着当其目标符合终结条件时,它将变得无效,其中一个在之后被处理)。

    顺便说一下,如果我设计一个基于GC的框架,我会添加一些其他优点:(1)声明引用类型的方法 存储位置 作为一个主要对其他人感兴趣的参考,以及(2)各种 弱引用 这可能意味着对对象的唯一引用是“对其他人感兴趣”的存储位置。虽然 弱引用 是一种有用的类型,将弱引用转化为强引用的行为可能会阻止系统认识到,如果目标消失,没有人会介意。