【发布时间】:2021-10-28 14:49:53
【问题描述】:
我正在阅读这个coroutines 动手教程Coroutines-Channels。所以有这个任务是使用channels同时获取贡献者并显示中间进度,参见Here
以下是建议解决方案的sn-p
suspend fun loadContributorsChannels(
service: GitHubService,
req: RequestData,
updateResults: suspend (List<User>, completed: Boolean) -> Unit) = coroutineScope {
........
.........
val channel = Channel<List<User>>()
for (repo in repos) {
launch {
val users = service.getRepoContributors(req.org, repo.name) // suspend function
.also { logUsers(repo, it) }
.bodyList()
channel.send(users) // suspend function
}
}
var allUsers = emptyList<User>()
repeat(repos.size) {
val users = channel.receive() // suspend function
allUsers = (allUsers + users).aggregate()
updateResults(allUsers, it == repos.lastIndex) // suspend function
}
}
函数loadContributorsChannels() 在使用Default dispatcher.See here 的coroutine 内调用。我有 2 个问题。
-
在上面的 sn-p 中,
allUsers被同时修改,因为我们已经在使用Default dispatcher的coroutine中? -
如果我像下面这样更改代码序列,为什么会得到不正确的结果?上面的代码和下面的sn-p有什么区别?
val contributorsChannel = Channel<List<User>>() var contributors = emptyList<User>() for(repo in repos) { launch { val contributorsPerRepo = service .getRepoContributors(req.org, repo.name) // suspend function .also { logUsers(repo, it) } .bodyList() contributors = (contributors + contributorsPerRepo).aggregate() contributorsChannel.send(contributors) // suspend function } } repeat(repos.size) { updateResults(contributorsChannel.receive(), it == repos.lastIndex) // suspend functions }
这是因为并发修改还是我遗漏了什么?
【问题讨论】:
标签: kotlin concurrency kotlin-coroutines kotlinx.coroutines.channels