haw*_*eye 11 concurrency multithreading scala clojure
Clojure 有一个Atom,用于以同步和独立的方式更改线程之间的状态,这不是STM的一部分.你这样使用它:
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
我的问题是:Clojure的Atom的Scala等价物是什么?
正如@Shepmaster和@ om-nom-nom所说,它是一个包装器java.util.concurrent.atomic.Atomic....
等效的包装器可能如下所示:
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
}
例如:
val myAtom = Atom(0)
myAtom()  // --> 0
myAtom.transformAndGet(_ + 1) // --> 1
myAtom()  // --> 1
myAtom.transformAndGet(_ * 4) // --> 4
如果使用Scala-STM,则通过使用.single视图将该功能内置到STM引用中:
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
优点是Ref.apply已经为您提供了原始类型的专用单元格,例如Int代替AnyRef(盒装).
| 归档时间: | 
 | 
| 查看次数: | 1240 次 | 
| 最近记录: |