Kotlin协同路由互斥对象所有者使用

Kotlin协同路由互斥对象所有者使用,kotlin,mutex,kotlin-coroutines,Kotlin,Mutex,Kotlin Coroutines,kotlinx.coroutines.sync.Mutex中的owner的预期用途是什么 据我所知,一个互斥锁。withLock将在第一个之后进行任何调用协同路由(巫婆锁定了互斥锁),等待它解锁,然后自己持有锁 那么,是什么导致了以下错误 2019-12-06 15:29:30.508 6380-6840/com.[...] E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-3 Process: com.[...],

kotlinx.coroutines.sync.Mutex
中的
owner
的预期用途是什么

据我所知,一个
互斥锁。withLock
将在第一个之后进行任何调用协同路由(巫婆锁定了互斥锁),等待它解锁,然后自己持有锁

那么,是什么导致了以下错误

2019-12-06 15:29:30.508 6380-6840/com.[...] E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-3
    Process: com.[...], PID: 6380
    java.lang.IllegalStateException: Already locked by [...].source.local.configuration.ConfigurationCacheSourceImpl@c86499c
        at kotlinx.coroutines.sync.MutexImpl.lockSuspend(Mutex.kt:208)
        at kotlinx.coroutines.sync.MutexImpl.lock(Mutex.kt:187)
        at com.[...].source.local.cache.CacheSource.invoke$suspendImpl(CacheSource.kt:52)
        at com.[...].source.local.cache.CacheSource.invoke(Unknown Source:0)
        at com.[...].source.local.cache.ICacheSource$DefaultImpls.invoke$default(CacheSource.kt:10)
        at com.[...].repository.ConfigurationRepositoryImpl.getStuff(ConfigurationRepository.kt:14)
        at com.[...].interactor.ConfigurationInteractorImpl.getStuff(CongifurationInteractor.kt:16)
        at com.[...]
        at com.[...]
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740)
请注意,我总是在其
with lock
调用中使用相同的
所有者
,如下所示:

abstract class CacheSource<T>(
    private val cacheMutex = Mutex()

    override suspend operator fun invoke(
        [...]
    ): T = cacheMutex.withLock(this) {
        [...]
    }
}
抽象类缓存源(
private val cacheMutex=Mutex()
重写挂起运算符调用(
[...]
):T=cacheMutex.withLock(此){
[...]
}
}
并根据:

owner-用于调试的可选所有者令牌。当指定了所有者(非空值)且此互斥锁已使用相同令牌(相同标识)锁定时,此函数将抛出IllegalStateException


互斥体
中的
所有者
的用途在相应参数的文档中进行了解释。协同路由互斥体是不可重入的,因此相对容易陷入“死锁”在尝试重新获取已获取的锁时。此外,在实现复杂的锁定模式(如移交锁定)时,可能很容易搞乱并释放不应该持有的锁

因此,
owner
是调试的可选辅助工具。如果指定了
owner
(非空值),并且互斥锁已与同一所有者(相同身份)锁定,然后
lock
函数抛出
IllegalStateException
。类似地,试图用错误的所有者
unlock
也抛出
IllegalStateException

有关详细信息,请参阅
锁定
解锁
功能的文档:


互斥体是可重入的吗?根据,所有者的作用域应为获取锁的协同路由。如果您从所有协同路由中传递同一个,它将抛出异常,而不是等待获取锁。传递所有者对象的点就是我上面提到的,获取异常而不是死锁。coro的所有者utine互斥不是一个线程,而是一个协程。因此,您传入的所有者对象必须对应于一个不同的协程。这样,如果同一个协程尝试重新传入它,您将得到一个错误而不是死锁。您也可以完全忽略此参数,并为错误代码获得死锁。我认为最好的做法是传入对应于协同程序,因此您会收到任何作为例外的重返尝试信号。我感谢您的解释,但我也必须这么说(大多数)官方文档或教程中没有这方面的内容,虽然对于熟悉互斥体的人来说可能很明显,但对于像我这样的新手来说,这肯定会让人困惑。所有者是一个可选参数,仅用于高级用例。我看不出有任何理由为这样的功能编写教程。