为什么抛出异常时 Scala 中的原子块 运行 两次?
Why is an atomic block in Scala run twice when exception gets thrown?
代码:
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 文档 this page 的底部是这样说的:
To make nesting very cheap, ScalaSTM tries to flatten all of the
nesting levels together into a single top-level transaction. If an
inner transaction throws an exception then there isn’t enough
information to perform the partial rollback, so ScalaSTM restarts the
entire transaction in a mode that does exact nesting. This
optimization is called subsumption.
那么会发生什么:
- 整个事情都是作为 "flattened" t运行saction
尝试的
last
设置为 "outer"
last
设置为 "inner"
"inner"
打印
- 内部原子块抛出异常,外部块不抛出异常
- ScalaSTM 不知道如何回滚内部 t运行saction 因为它 运行 "flattened" 所以它回滚整个事情(
last
是现在回到 "none"
) 并重试 "non-flattened"
last
设置为 "outer"
last
设置为 "inner"
"inner
打印
- 内部原子块抛出异常,被外部块捕获
- 这次因为没有扁平化,只能回滚内部块,
last
设置回"outer"
。
代码:
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 文档 this page 的底部是这样说的:
To make nesting very cheap, ScalaSTM tries to flatten all of the nesting levels together into a single top-level transaction. If an inner transaction throws an exception then there isn’t enough information to perform the partial rollback, so ScalaSTM restarts the entire transaction in a mode that does exact nesting. This optimization is called subsumption.
那么会发生什么:
- 整个事情都是作为 "flattened" t运行saction 尝试的
last
设置为"outer"
last
设置为"inner"
"inner"
打印- 内部原子块抛出异常,外部块不抛出异常
- ScalaSTM 不知道如何回滚内部 t运行saction 因为它 运行 "flattened" 所以它回滚整个事情(
last
是现在回到"none"
) 并重试 "non-flattened" last
设置为"outer"
last
设置为"inner"
"inner
打印- 内部原子块抛出异常,被外部块捕获
- 这次因为没有扁平化,只能回滚内部块,
last
设置回"outer"
。