Kotlin 如何锁定两个协同路由,但允许原始协同路由进入
我启动了一个合作项目来做一些工作。我需要一个互斥锁。但是,有时Kotlin 如何锁定两个协同路由,但允许原始协同路由进入,kotlin,mutex,Kotlin,Mutex,我启动了一个合作项目来做一些工作。我需要一个互斥锁。但是,有时doWork函数会再次调用one(),但会发生死锁 private val scope = CoroutineScope(Dispatchers.IO) private val a = A() fun start() { scope.launch { a.one() } } 然后 我所做的会导致死锁,因为one()已被锁定。理想情况下,我会在Java中获得类似于@Synchronized的东西,它允
doWork
函数会再次调用one()
,但会发生死锁
private val scope = CoroutineScope(Dispatchers.IO)
private val a = A()
fun start() {
scope.launch {
a.one()
}
}
然后
我所做的会导致死锁,因为one()
已被锁定。理想情况下,我会在Java中获得类似于@Synchronized
的东西,它允许相同的线程进入,但我知道协同路由不是线程
我能用什么来解决这个问题吗?我不能太多地改变这个问题,因为有些代码我自己也不能改变。使用通信协程
您说过无法更改某些代码,因此此解决方案可能不适合您。不过,锁通常不适合协同程序。一个更惯用的解决方案是通过让不同的协同程序彼此通信来管理共享资源
不使用锁,而是将其设置为只允许一个协程访问共享资源。其他协同程序可能会将工作发送给it部门,但它们可能不会直接访问共享资源。这保证在任何给定的时间只有一个东西访问共享资源
假设我们的共享资源是一个函数doSomething()
,它不是线程安全的,一次只能由一个线程调用。我们启动一个将接收请求的协同程序。此协同路由是共享资源的“所有者”。任何要调用doSomething()
的操作都必须通过向该参与者发送请求来完成。很多东西可能会向参与者发送请求,但它会一次处理一个请求。每次参与者收到请求时,它只调用doSomething()
函数。这里我使用了一个Request
类,它可以包含您需要传递给共享函数的任何参数。看起来是这样的:
数据类请求(…)
有趣的开始{
val requests=scope.actor{
每个{请求->
剂量测定(请求)
}
}
范围.发射{
请求。发送(请求(…)
}
}
暂停娱乐内容(请求:请求){
//做一些非线程安全的工作
}
您所说的被称为“可重入锁”,通常被认为是糟糕的设计。相反,您可以将一个布尔参数传递给doWork
,告诉它是否需要获取锁。请参阅
class A {
private val mutex = Mutex()
suspend fun one() {
mutex.withLock {
doWork()
}
}
}