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
はありません。update
並行マップは、可変マップ API にいくつかのアトミック操作を追加しますが、私が必要とするものではありません。これは次のようになります。
def replace(k: A, f: B => B): Option[B]
私はScalaSTMを使用できることを知っていますTMap
:
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 でこの問題に対する「正しい」答えのようなものはありますか?