Code:
object Blub {
import scala.concurrent.stm._
val last = Ref("none")
def bla() = atomic { implicit txn =>
last() = "outer"
try {
atomic { implicit txn =>
last() = "inner"
println(last())
throw new RuntimeException
}
} catch {
case _: RuntimeException =>
}
}
def main(args: Array[String]): Unit = {
bla()
println("Result: "+last.single())
}
}
输出:
inner
inner
Result: outer
谁能解释为什么内部原子块运行两次?我知道由于异常,它会回滚,因此最终结果。但我不明白为什么它会第二次运行代码。
ScalaSTM 文档的本页底部是这样说的:
为了使嵌套变得非常便宜,ScalaSTM试图将所有嵌套扁平化。 将级别嵌套到单个顶级事务中。如果 内部事务抛出异常,则没有足够的异常 信息来执行部分回滚,因此 ScalaSTM 重新启动 整个事务处于执行精确嵌套的模式下。这 优化称为包容。
所以发生的事情是:
- 整个事情被尝试为"扁平化"事务
last
设置为"outer"
last
设置为"inner"
- 打印
"inner"
- 内部原子块引发异常,外部块不会
- ScalaSTM 不知道如何回滚内部事务,因为它运行"扁平化",所以它会回滚整个事情(
last
现在回到"none"
(并重试它"非扁平化"> last
设置为"outer"
last
设置为"inner"
- 打印
"inner
- 内部原子块引发异常,该异常被外部块捕获
- 这次由于它是非扁平的,它只能回滚内部块,
last
被设置回"outer"
。