假设我想在 Scala 中使用可变映射来跟踪我看到某些字符串的次数。在单线程上下文中,这很容易:
import scala.collection.mutable.{ Map => MMap }
class Counter {
val counts = MMap.empty[String, Int].withDefaultValue(0)
def add(s: String): Unit = counts(s) += 1
}
不幸的是,这不是线程安全的,因为get
andupdate
不会自动发生。
并发映射向可变映射 API添加了一些原子操作,但不是我需要的,它看起来像这样:
def replace(k: A, f: B => B): Option[B]
import scala.concurrent.stm._
class Counter {
val counts = TMap.empty[String, Int]
def add(s: String): Unit = atomic { implicit txn =>
counts(s) = counts.get(s).getOrElse(0) + 1
}
}
但是(目前)这仍然是一个额外的依赖项。其他选项将包括参与者(另一个依赖项)、同步(可能效率较低)或 Java 的原子引用(较少惯用)。
一般来说,我会避免在 Scala 中使用可变映射,但我偶尔会需要这种东西,最近我使用了 STM 方法(而不是只是交叉手指,希望我不会被天真解决方案)。
我知道这里有很多权衡(额外的依赖与性能与清晰度等),但在 Scala 2.10 中是否有类似“正确”的答案?