猫效应3的Ref和AtomicCell有什么区别?

问题描述 投票:0回答:1

在 Cats Effect 3 中,它们提供了并发原语,如

Ref
AtomicCell
。但我不确定两者之间有什么不同。

什么时候我们需要

AtomicCell
而不是
Ref
?它们有什么特点?缺少哪些功能?

scala cats-effect
1个回答
0
投票

让我们从比较 API 开始:

Ref
定义类似:

的方法
def access: F[(A, (A) => F[Boolean])]
def modify[B](f: (A) => (A, B)): F[B]
def modifyState[B](state: State[A, B]): F[B]
def set(a: A): F[Unit]
def tryModify[B](f: (A) => (A, B)): F[Option[B]]
def tryModifyState[B](state: State[A, B]): F[Option[B]]
def tryUpdate(f: (A) => A): F[Boolean]
def update(f: (A) => A): F[Unit]
// and methods build on top of them

这些方法要求我们提供一个纯函数来修改状态,或者只从中读取/写入一个值。这就像

var
的更安全版本。

AtomicCell
定义类似:

的方法
def evalGetAndUpdate(f: (A) => F[A]): F[A]
def evalModify[B](f: (A) => F[(A, B)]): F[B]
def evalUpdate(f: (A) => F[A]): F[Unit]
def evalUpdateAndGet(f: (A) => F[A]): F[A]
def get: F[A]
def modify[B](f: (A) => (A, B)): F[B]
def set(a: A): F[Unit]
// and methods build on top of them

它允许使用适用于

F
的方法更新状态 - 也就是说,您的状态可以通过副作用进行更新。所以这就像一个更安全的:


private var a: A

def update(f: A => A): A = synchronized {
  a = f(a)
}

为什么这很重要? 文档告诉我们原因

AtomicCell 可以被视为 Mutex 和 Ref 的组合:

import cats.effect.{IO, Ref}
import cats.effect.std.Mutex

trait State
class Service(mtx: Mutex[IO], ref: Ref[IO, State]) {
  def modify(f: State => IO[State]): IO[Unit] = 
    mtx.lock.surround {
      for {
        current <- ref.get
        next <- f(current)
        _ <- ref.set(next) 
      } yield ()
    }
}

以下内容与上面的示例等效:

import cats.effect.IO
import cats.effect.std.AtomicCell

trait State class Service(cell: AtomicCell[IO, State]) {
  def modify(f: State => IO[State]): IO[Unit] = 
    cell.evalUpdate(current => f(current)) }

换句话说:

  • Ref
    是“更精简”,但只有在不需要“事务”的情况下才方便使用,并且不存在并发访问破坏事物的风险(例如,线程 1 读取并开始阻塞计算,线程 2 读取并开始阻塞计算)。开始阻塞计算,线程 2 写入,线程 1 写入...1 个更新已丢失!)
  • AtomicCell
    正在阻塞新的更新,直到开始的更新完成(线程 1 读取并开始长计算,线程 2 尝试读取...并且必须等待,线程 1 完成,线程 2 可以读取值...),所以使用起来应该更安全,但互斥可能会带来一些开销

对于在单个

Ref
中处理的事情,或者不太可能并发更新的事情(例如,使用管理命令更改一些全局标志),我可能更喜欢
Fiber
。或者在测试和原型设计期间进行简单的模拟。

当我必须将状态保留在内存中,同时将其视为具有一定事务性但不一定具有持久性的简单“内存数据库”时,我会选择

AtomicCell
(与STM类似的用例,但在这里我们允许副作用,所以退休是不可能的)。

© www.soinside.com 2019 - 2024. All rights reserved.