Moh*_*hit 2 kotlin-native kotlin-multiplatform kotlin-multiplatform-mobile
我正在关注此处的Kotlin/Native Concurrency 实践。我无法理解最后一个示例,为什么“上面修改后的 saveToDb 函数现在处理后台调用,并且仅捕获函数参数。这不会冻结父类”
class CountingModelSafer{
var count = 0
fun increment(){
count++
saveToDb(count)
}
private fun saveToDb(arg:Int) = background {
println("Doing db stuff with $arg, in main $isMainThread")
}
}
Run Code Online (Sandbox Code Playgroud)
[请注意,在这些示例中,在背景内部,传递的 lambda 被冻结]
下面的代码片段会导致整个 CountingModel 被冻结,但上面的代码片段不会被冻结。有人可以帮我理解为什么会这样吗?
class CountingModel{
var count = 0
fun increment(){
count++
background {
saveToDb(count)
}
}
private fun saveToDb(arg:Int){
//Do some db stuff
println("Saving $arg to db")
}
}
Run Code Online (Sandbox Code Playgroud)
当然。我写了示例,所以让我尝试解释一下。
background {
saveToDb(count)
}
Run Code Online (Sandbox Code Playgroud)
该background函数采用 lambda 参数。Lambda 可以“捕获”状态并影响它。我的意思是,忘记“冻结”,您通常会期望更改 的值count会更改源值。因此,如果我们忘记“冻结”,则 ifcount从 0 开始,则以下结果将count是 1:
background {
count++
}
Run Code Online (Sandbox Code Playgroud)
为了实现这一点,lambda 需要引用count,并且引用count意味着您将尊重持有它的类。更正式地说,代码应如下所示:
background {
this.count++
}
Run Code Online (Sandbox Code Playgroud)
我们不需要声明this.count,但这只是因为this是假设的。
Lambda 需要访问它们引用的状态,而这一切都不是魔法。Lambda 具有状态,即它们捕获的对象。冻结状态是指被冻结者接触到的所有状态。对于 lambda 函数,这意味着代码引用的任何内容。
在这种情况下:
private fun saveToDb(arg:Int) = background {
println("Doing db stuff with $arg, in main $isMainThread")
}
Run Code Online (Sandbox Code Playgroud)
arg:Int是一个参数。arg被冻结,但 lambda 中没有任何内容捕获父类。如果你this.arg这样写的话就会出错。arg是本地的。冻结它不会级联到父类。
我开始编写一个 Intellij/AS 插件来帮助警告您这些可能的情况,因为这是最有可能让人绊倒的事情,但 Kotlin 团队告诉我,他们决定取消这种内存模型。因此,该插件的工作停止了。明年某个时候,这将不再是问题。
然而,学习这种记忆模型是有用的。从线程的角度来看,开发人员往往会随意做一些危险的事情。Kotlin/Native 限制性线程模型迫使您重新思考如何构建代码。这不一定是坏事。
但我离题了。模式正在发生变化。与此同时,请注意你的捕获状态。
| 归档时间: |
|
| 查看次数: |
227 次 |
| 最近记录: |