参考周期的实际例子是什么? [英] What are the practical examples of reference cycles?

查看:91
本文介绍了参考周期的实际例子是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

垃圾收集器具有处理参考周期的功能.据我了解,这对于使用GC的所有语言都是必需的.

Garbage collectors have functionality to deal with reference cycles. As far, as I understand, this is necessary for all languages with GC.

但是我不明白,为什么不能创建一种避免引用循环的语言,必要时使用一些弱引用.

But I do not understand, why there can not be created language avoiding reference cycles, using some weak references, if necessary.

编程中出现不可避免的参考周期的现实例子是什么?

What are the real life examples of unavoidable reference cycles, arising in programming?

推荐答案

您不能创建一种避免引用循环的编程语言,因为这是应用程序程序员的责任,而不是创建循环.您只能创建一种语言,要求程序员始终承担这种责任.

You can not create a programming language avoiding reference cycles, as it would be the responsibility of the application programmer, not to create the cycles. You could only create a language which requires the programmer to always take that responsibility.

这是数据结构的基本设计,它可以允许或不允许循环.例如.在Java中,List是引用列表,因此,直接或间接在自身中存储List不会有问题.但是举一个更加直接的示例,它具有一个双向链接列表,每个节点都有一个指向其下一个节点和上一个节点的指针.这已经足以形成参考周期:

It’s the fundamental design of the data structures which may allow cycles or not. E.g. in Java, a List is a list of references, therefore, there is no problem in storing a List in itself, directly or indirectly. But to name a more straight-forward example, with a doubly linked list, each node has a pointer to its next node and its previous node. This is already enough to form reference cycles:

 ┌──────┐             ┌──────┐             ┌──────┐             ┌──────┐             
 │      │ -next-----> │      │ -next-----> │      │ -next-----> │      │
 │ Node │             │ Node │             │ Node │             │ Node │
 │      │ <-previous- │      │ <-previous- │      │ <-previous- │      │
 └──────┘             └──────┘             └──────┘             └──────┘

这已经形成了多个循环,即两个相邻节点之间通过它们的previousnext引用而形成的短循环,而且还间接地在其他节点之间形成了循环.

This is already forming multiple loops, short loops between two adjacent nodes via their previous and next references, but also indirectly between the other nodes.

要通过弱引用减少这些循环,Node类的设计者必须决定是使next还是previous引用弱.它们中的任何一个都将破坏基本功能之一:

To cut these loops via weak references, the designer of the Node class would have to decide whether to make the next or previous reference weak. Either of them would destroy one of the fundamental functionality:

  • 如果您有第一个节点的引用,则可以通过一系列next引用来到达并遍历所有节点
  • 如果您有对最后一个节点的引用,则可以通过一系列previous引用来到达并遍历所有节点
  • 实际上,引用任何个链接的节点就足以到达所有节点
  • 如果所有节点都不可达,则所有节点都可以收集垃圾
  • If you have a reference to the first node, you can reach and traverse all nodes via a chain of next references
  • If you have a reference to the last node, you can reach and traverse all nodes via a chain of previous references
  • In fact, having a reference to any of the chained nodes is sufficient to reach all nodes
  • If all nodes are unreachable, all nodes can get garbage collected

如果您声明两个引用之一为弱引用,则不能假定对一个节点的引用使所有节点不再活动.如果next较弱,则要求您始终保留对最后一个节点的引用,以防止突然删除下一个节点.如果previous较弱,则必须始终保持对第一个节点的引用.

If you declare one of the two references weak, you can not assume that a reference to one node keeps all nodes alive anymore. If next was weak you were required to always keep a reference to the last node to prevent sudden removal of next nodes. If previous was weak, you had to keep a reference to the first node all the time.

因此,要求开发人员始终通过弱引用来减少循环将对方法产生根本性的限制,因此必须对软件进行设计.再举一个例子,考虑一个注册了侦听器的组件,该组件将在事件发生时修改该组件(或另一个组件引用了前者),从而形成循环循环.将听众的参考调弱会暗示它可能会突然消失而没有原因.

So requiring the developer to always cut loops via weak references would cause fundamental restrictions to the way, the software has to be designed. As another example, consider a component to which you register a listener will modify the component when an event happened (or another component having a reference to the former), therefore forming a cyclic loop. Making the listener reference weak would imply that it could suddenly disappear without a cause.

也就是说,即使弱引用本身也是垃圾收集器自然进行图遍历的功能,因为只有那些垃圾收集者在发现它们的存在时才能廉价地行动.当引用计数系统发现最后一个/唯一的现有强引用已被删除时,它可以轻松释放对象,但是当对象被删除时,它需要对所有现有的弱引用进行额外的簿记以 clear 释放.

That said, even the weak references themselves are a feature that is naturally provided by garbage collectors doing graph traversal, as only those can cheaply act when discovering their existence. A reference counting system can easily free an object when it discovers that the last/only existing strong reference has been removed, but it would need additional bookkeeping of all existing weak references to clear them when the object has been freed.

这就是要点,引用计数根本不再有意义.实现不再是简单的事情(这是唯一的优势),同时又效率低下,因为遍历对象图时(例如遍历链表),您必须永久性地更新引用计数器(在线程中)一种安全的方式(如果您的语言支持多线程),而遍历垃圾收集器仅在必须检查可回收内存时才需要执行某些操作.而且它只需要遍历活着的对象,因此无所事事的时间越长,下一个周期的工作就越少.

This is the point, where reference counting simply makes no sense anymore. It wouldn’t be simple to implement anymore (which is the only advantage), while being inefficient at the same time, as when traversing an object graph, like iterating over the linked list, you permanently have to update reference counters (in a thread safe way if your language supports multi-threading), whereas a traversing garbage collector only has to do something when it has to check for reclaimable memory. And it only has to traverse alive objects, thus the longer it can get away with doing nothing, the less work it will have on the next cycle.

这篇关于参考周期的实际例子是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆