Angenommen, ich möchte eine veränderbare Map in Scala verwenden, um zu verfolgen, wie oft ich einige Strings gesehen habe. In einem Kontext, single-threaded, dann ist dies einfach:Thread-sichere Umwandlung eines Wertes in eine veränderbare Map
import scala.collection.mutable.{ Map => MMap }
class Counter {
val counts = MMap.empty[String, Int].withDefaultValue(0)
def add(s: String): Unit = counts(s) += 1
}
Leider ist dies nicht Thread-sicher, da die get
und die update
atomar nicht passieren.
Concurrent maps hinzufügen a few atomic operations zum wandelbar Karte API, aber nicht die, die ich brauche, die wie folgt aussehen würde:
def replace(k: A, f: B => B): Option[B]
Ich weiß, ich ScalaSTM ‚s nutzen können 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
}
}
Aber (für jetzt), das ist immer noch eine extra Abhängigkeit. Andere Optionen würden Akteure (eine weitere Abhängigkeit), Synchronisation (möglicherweise weniger effizient) oder Javas atomic references (less idiomatic) einschließen.
Im Allgemeinen würde ich veränderbare Karten in Scala vermeiden, aber ich habe gelegentlich solche Dinge gebraucht, und zuletzt habe ich den STM-Ansatz benutzt (anstatt nur die Daumen zu drücken und zu hoffen, dass ich nicht komme) von der naiven Lösung gebissen).
Ich weiß, dass es hier eine Reihe von Kompromissen gibt (zusätzliche Abhängigkeiten vs. Leistung vs. Klarheit usw.), aber gibt es in Scala 2.10 so etwas wie eine "richtige" Antwort auf dieses Problem?
was über ein Akka Schauspieler, die auf die wandelbaren Karte schreibt? 'Counter.add' sendet nur eine Feuer-und-Vergessen-Nachricht an sie. Was das Lesen betrifft, können sie je nach Bedarf gleichzeitig stattfinden oder auch durch den Akteur gehen. – gourlaysama