Scala中monad中的重入锁
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala中monad中的重入锁相关的知识,希望对你有一定的参考价值。
我的一位同事在一些Scala代码中使用Java ReentrantReadWriteLock
说明如下:
在这里获取锁是有风险的。它是“可重入的”,但内部依赖于线程上下文。
F
可以在不同的线程中运行相同计算的不同阶段。你很容易造成僵局。
F
在这里指的是一些有效的monad。
基本上我要做的是在同一个monad中获得两次相同的重入锁。
有人可以澄清为什么这可能是一个问题吗?
代码分为两个文件。最外面的一个:
val lock: Resource[F, Unit] = for {
// some other resource
_ <- store.writeLock
} yield ()
lock.use { _ =>
for {
// stuff
_ <- EitherT(store.doSomething())
// other stuff
} yield ()
}
然后,在store
:
import java.util.concurrent.locks.{Lock, ReentrantReadWriteLock}
import cats.effect.{Resource, Sync}
private def lockAsResource[F[_]](lock: Lock)(implicit F: Sync[F]): Resource[F, Unit] =
Resource.make {
F.delay(lock.lock())
} { _ =>
F.delay(lock.unlock())
}
private val lock = new ReentrantReadWriteLock
val writeLock: Resource[F, Unit] = lockAsResource(lock.writeLock())
def doSomething(): F[Either[Throwable, Unit]] = writeLock.use { _ =>
// etc etc
}
两段代码中的writeLock
是相同的,它是包裹cats.effect.Resource[F, Unit]
的ReentrantReadWriteLock
的writeLock
。我之所以用这种方式编写代码有一些原因,所以我不想深入研究。我想了解为什么(据我的同事,至少),这可能会破坏一些东西。
此外,我想知道Scala中是否有一些替代方案可以允许这样的事情而不会有死锁的风险。
IIUC你的问题:
您希望与资源lock.lock
和lock.unlock
操作的每次交互都发生在同一个线程中。
1)由于你在这里使用任意效果F
,因此完全没有保证。可以编写一个F
的实现来执行新线程中的每个操作。
2)即使我们假设F
是IO
然后doSomething
的身体有人可以做IO.shift
。因此包括unlock
在内的下一步行动将在另一个线程中发生。可能它不可能与doSomething
的当前签名,但你明白了。
此外,我想知道Scala中是否有一些替代方案可以允许这样的事情而不会有死锁的风险。
你可以看看scalaz zio STM
。
以上是关于Scala中monad中的重入锁的主要内容,如果未能解决你的问题,请参考以下文章