我有以下课程:
class SdkWrapper(private val sdk: Sdk) {
private var inited = false
suspend fun doSomething() = withContext(Dispatchers.IO) {
if (inited.not()) init()
useSdk()
}
private fun init() {
// takes a long time
sdk.init()
inited = true
}
// has to be done asynchronously
// sdk.init() has to have been called before using this
private fun useSdk() {
}
}
class Sdk {
// must only be done once
fun init() {}
}在执行useSdk()之前,我必须调用sdk.init(),但是必须只调用sdk.init()一次,而不能再调用一次。
使用我的当前解决方案,如果doSomething被快速调用两次(第二次在sdk.init()仍在运行时发生),我将调用sdk.init()两次,因为inited: Boolean仍然是false。
如果我将inited的分配向上移动,如下所示:
private fun init() {
inited = true
sdk.init()
}doSomething()被快速调用了两次,第二个调用将在其‘init()’完成之前使用sdk。
我试着用:
suspend fun doSomething() = synchronized(this){
withContext(Dispatchers.IO) {
if (inited.not()) init()
useSdk()
}
}但是在IntelliJ中接收一个错误:
withContext暂停点在一个关键区域内。
我假设synchronized无论如何不会在这里工作,因为我们离开了主线程,而doSomething()是在withContext块还在运行时完成的?
我如何解决手头的问题,基本上是:doSomething()一次只能运行一次?
发布于 2020-10-09 10:34:53
您可以使用Mutex代替synchronized {...}:
class SdkWrapper(private val sdk: Sdk) {
...
private val mutex = Mutex()
suspend fun doSomething() = mutex.withLock {
withContext(Dispatchers.IO) {
if (inited.not()) init()
useSdk()
}
}
...
}您可以查看有关Coroutines和互斥这里的官方文档。
https://stackoverflow.com/questions/64277015
复制相似问题