4

问题陈述

我有两台机器 A 和 B,它们都运行 Clojure。

B有一些内存数据结构。

A 持有一个对象 A_P,它是 B 内存中某个对象 B_O 的引用/指针。

现在,只要 A_P 没有被 A GC-ed,我不希望 B_O 被 B GC-ed。

但是,一旦 A_P 已被 A GC-ed(并且 A 中的其他任何内容都没有引用 B_O,B 中的其他任何内容都没有引用 B_O),那么我希望 B_O 可以被 GC-ed。

带有析构函数的语言解决方案

在 C++ 中,这很容易——我使用析构函数。当 A_P 被 GC-ed 时,A 向 B 发送一个 msg 以减少对 B_O 的外部引用的数量,当它为 0 并且对 B_0 的内部引用也为 0 时,B_O 被 GC-ed。

Java/Clojure 中的解决方案?

现在,我知道 Java 没有析构函数。但是,我想知道 Clojure 是否有办法解决这个问题。

谢谢!

4

4 回答 4

3

如果没有真正的分布式垃圾收集器,就不存在好的解决方案。即使在 C++ 中,你也不能安全地做到这一点,因为你实现了引用计数并假装它是一个真正的垃圾收集器;但是如果两个对象跨机器分界指向彼此,并且都在本地未引用,则它们仍然具有非零引用计数并且无法被收集。

于 2012-10-10T04:28:02.987 回答
1

不,由于 JVM 的自动内存管理模型,Clojure(基于 JVM,CLR)没有“C++ 类型析构函数”。有诸如终结器之类的东西,但建议不要使用它们。相反,您应该基于消息传递机制而不是 A 机器对 B 中的数据进行“指针/引用”来建模您的解决方案。我知道这个答案非常高级,因为您没有在问题中提供任何具体的问题细节。如果您需要有关如何解决特定问题的更多详细信息,请提供完整的上下文,我相信有人能够帮助您。

于 2012-10-10T04:24:20.753 回答
1

这是一个本质上很难解决的问题:分布式垃圾问题即使不是不可能解决也非常困难。

finalize()但是,您可能只能使用 Java 终结器并覆盖该方法使其工作。然后,您可以实现一种类似于您为 C++ 描述的消息传递技术。

这在更一般的情况下会出现问题(它不会帮助您在机器之间进行循环引用,正如 amalloy 指出的那样)并且还有一些其他的怪癖需要注意(主要是因为您无法准确控制终结器何时被调用) 但你也许可以让它在你的特定情况下工作。

于 2012-10-10T06:35:33.247 回答
0

假设您使用 ref 或 atom 之类的数据结构在其中的某处保存数据结构 A,您可以使用侦听器来监视该结构的状态以删除 A,并且这些侦听器可以向 B 发送适当的消息。 clojure.data/diff可能是对于查找已删除的结构非常有用。

另一种选择是在 A 结构被取消引用后立即让负责这样做的函数发送消息。不过,作为其中的一部分,请确保该代码实际上负责删除 A,而不是其他一些更新。

于 2012-10-12T04:55:12.023 回答