What is the Scala equivalent of Clojure's Atom?

↘锁芯ラ 提交于 2020-01-12 07:01:28

问题


Clojure has an Atom for changing state between threads in a synchronous and independent manner, that is not part of the STM. You use it like this:

user=> (def my-atom (atom 0))
#'user/my-atom

user=> @my-atom
0

user=> (swap! my-atom inc)
1

user=> @my-atom
1

user=> (swap! my-atom (fn [n] (* (+ n n) 2)))
4

My question is: What is the Scala equivalent of Clojure's Atom?


回答1:


As @Shepmaster and @om-nom-nom said, it's a wrapper around java.util.concurrent.atomic.Atomic....

An equivalent wrapper could look like this:

import java.util.concurrent.atomic._
import scala.annotation.tailrec

object Atom {
  def apply[A](init: A): Atom[A] = new Impl(new AtomicReference(init))

  private class Impl[A](state: AtomicReference[A]) extends Atom[A] {
    def apply(): A = state.get()
    def update(value: A): Unit = state.set(value)
    def transformAndGet(f: A => A): A = transformImpl(f)

    @tailrec private final def transformImpl(fun: A => A): A = {
      val v    = state.get()
      val newv = fun(v)
      if (state.compareAndSet(v, newv)) newv
      else transformImpl(fun)
    }
  }
}
trait Atom[A] {
  def apply(): A
  def update(value: A): Unit
  def transformAndGet(f: A => A): A
}

Ex:

val myAtom = Atom(0)
myAtom()  // --> 0
myAtom.transformAndGet(_ + 1) // --> 1
myAtom()  // --> 1
myAtom.transformAndGet(_ * 4) // --> 4

If you use Scala-STM, that functionality is built into STM references, by using the .single view:

scala> import scala.concurrent.stm._
import scala.concurrent.stm._

scala> val myAtom = Ref(0).single
myAtom: scala.concurrent.stm.Ref.View[Int] = 
        scala.concurrent.stm.ccstm.CCSTMRefs$IntRef@52f463b0

scala> myAtom()
res0: Int = 0

scala> myAtom.transformAndGet(_ + 1)
res1: Int = 1

scala> myAtom()
res2: Int = 1

scala> myAtom.transformAndGet(_ * 4)
res3: Int = 4

The advantage is that Ref.apply will already give you specialised cells for the primitive types, e.g. Int instead of AnyRef (boxed).




回答2:


It's not Scala-specific, but I'd reach for AtomicReference first in Java land. How much of atoms functionality do you want/need?



来源:https://stackoverflow.com/questions/21806074/what-is-the-scala-equivalent-of-clojures-atom

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!