同步和 withContext
Synchronized and withContext
我有以下 class:
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()
仍然 运行ning 时),我会调用 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 中收到错误:
the withContext suspension point is inside a critical section
我假设 synchronized
无论如何都不会在这里工作,因为我们离开了主线程并且 doSomething()
完成了,而 withContext
块仍然是 运行宁?
我如何解决手头的问题,基本上是:doSomething()
应该一次只 运行 一次?
您可以使用互斥锁代替 synchronized {...}
:
class SdkWrapper(private val sdk: Sdk) {
...
private val mutex = Mutex()
suspend fun doSomething() = mutex.withLock {
withContext(Dispatchers.IO) {
if (inited.not()) init()
useSdk()
}
}
...
}
协程和互斥的官方文档可以看看here。
我有以下 class:
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()
仍然 运行ning 时),我会调用 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 中收到错误:
the withContext suspension point is inside a critical section
我假设 synchronized
无论如何都不会在这里工作,因为我们离开了主线程并且 doSomething()
完成了,而 withContext
块仍然是 运行宁?
我如何解决手头的问题,基本上是:doSomething()
应该一次只 运行 一次?
您可以使用互斥锁代替 synchronized {...}
:
class SdkWrapper(private val sdk: Sdk) {
...
private val mutex = Mutex()
suspend fun doSomething() = mutex.withLock {
withContext(Dispatchers.IO) {
if (inited.not()) init()
useSdk()
}
}
...
}
协程和互斥的官方文档可以看看here。