“to close over the enclosing scope/class” 是什么意思?(涉及IT技术)

17

Akka文档正在记录使用Props的危险变体:

// NOT RECOMMENDED within another actor:
// encourages to close over enclosing class
val props7 = Props(new MyActor)

然后继续陈述:

不建议在另一个actor中使用此方法,因为它鼓励关闭封闭作用域,导致Props不可序列化和可能的竞争条件(破坏了actor封装)。

能否有人解释一下"closing over the enclosing scope"的含义?我已经找了很久也没有找到。谢谢。

2个回答

20

在这个例子中,有一些棘手的地方需要注意,new Actor 作为所谓的“按名称”参数传递。将其视为类型为 () => Actor 的函数。每当Actor在重启期间由其监督者(re)创建时,都会调用此函数。

问题在于此函数是一个“闭包”(非常容易在Google上找到;)),这意味着它捕获并记住了需要的周围作用域中的所有内容(有时,但非常少时称为“堆栈剥离”)。例如val f = (a: Int) => a + xx来自哪里?它来自周围的作用域。赋给f的函数文字被称为“开放项”。运行时,函数文字变成函数值(这是说“对象”的花哨方式),当执行时关闭开放项,同时捕获周围作用域中的所有内容。这就是“闭包”名称的由来。

闭包非常有用,但您必须小心所涵盖的内容。有时x是一个def或更糟的是一个var,这导致f的结果不可预测,因为您无法控制f被调用/执行的时间。试试看!

Akka中两个非常常见的反模式是:

  1. 从内部类创建Actor时,关闭(外部)this引用。
  2. 在使用future响应消息时关闭def sender

顺便说一下,我故意给你提供了一堆花哨的术语可以去Google搜索;)

祝愉快编码!


2
感谢。详细的解释。 - Peter

8
作为对 @agilesteel 的回答的补充,以下是一些参考资料:
解释了什么是闭包:《Scala编程》第8.7章节,闭包
解释了为什么闭包会导致序列化问题:SIP-21 - Spores 这里有一个代码示例,展示了如何创建一个 Props 对象,由于闭包了一个不可序列化的对象而无法进行序列化,该示例基于 SIP-21 中的示例:
case class Helper(name: String)

object MyNonserializableObject {

    val helper = Helper("the helper")

    val props7 = Props(new MyActor(helper))
}

即使helper本身是可序列化的,但"new MyActor(helper)"是按名称传递的,因此捕获了this.helper,而this不可序列化。
您可以从Props apply方法的签名中看到actor参数是按名称传递的,在creator参数中有一个⇒。
def apply[T <: Actor](creator: ⇒ T)(implicit arg0: ClassTag[T]): Props

感谢您的贡献。 - Peter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接