scala - Scala 中的 monad 中的可重入锁

标签 scala locking deadlock reentrantlock reentrantreadwritelock

我的一位同事陈述了以下内容,关于使用 Java ReentrantReadWriteLock在一些 Scala 代码中:

Acquiring the lock here is risky. It's "reentrant", but that internally depends on the thread context. F may run different stages of the same computation in different threads. You can easily cause a deadlock.


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]包装 ReentrantReadWriteLockwriteLock .我以这种方式编写代码有一些原因,所以我不想深入研究。我只想了解为什么(至少根据我的同事的说法),这可能会破坏某些东西。

另外,我想知道 Scala 中是否有一些替代方案可以允许这样的事情而不会有死锁的风险。

最佳答案

IIUC你的问题:

您期望每次与资源的交互 lock.locklock.unlock Action 发生在同一个线程中。

1) 由于您使用的是任意效果,因此根本无法保证F这里。
可以编写 F 的实现在新线程中执行每个操作。

2) 即使我们假设 FIO然后是doSomething的正文有人可以做 IO.shift .所以接下来的操作包括unlock会发生在另一个线程中。可能无法使用 doSomething 的当前签名但你明白了。

Also, I'd like to know if there is some alternative in Scala that would allow something like this without the risk for deadlocks.



你可以看看scalaz zio STM .

关于scala - Scala 中的 monad 中的可重入锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55849330/

相关文章:

mysql - 什么时候在 MySQL 中锁定表(MyISAM 表)?

java - 执行器中的意外死锁

java - 从多个线程以相反顺序执行 equals() 时 Java 同步集合的问题

java - 哪个线程获取哪个对象的锁?

C# 锁定 WinForm 控件

scala - 我的 Apache Spark 代码如何发出周期性心跳?

class - scala 案例类问题

mysql - 由于多线程插入导致 MySQL 中的死锁

scala - 带有函数式编程的 ConcurrentHashMap。暂停 unsafeRun 安全吗?

c# - Scala,C# 等效于 F# 事件模式