What is the Scala equivalent of Clojure's Atom? What is the Scala equivalent of Clojure's Atom? multithreading multithreading

What is the Scala equivalent of Clojure's Atom?


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.tailrecobject 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()  // --> 0myAtom.transformAndGet(_ + 1) // --> 1myAtom()  // --> 1myAtom.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).singlemyAtom: scala.concurrent.stm.Ref.View[Int] =         scala.concurrent.stm.ccstm.CCSTMRefs$IntRef@52f463b0scala> myAtom()res0: Int = 0scala> myAtom.transformAndGet(_ + 1)res1: Int = 1scala> myAtom()res2: Int = 1scala> 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).


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