scala – 线程安全地转换可变地图中的值
发布时间:2020-12-16 19:04:26 所属栏目:安全 来源:网络整理
导读:假设我想在 Scala中使用可变地图来跟踪我看到一些字符串的次数.在单线程的上下文中,这很简单: import scala.collection.mutable.{ Map = MMap }class Counter { val counts = MMap.empty[String,Int].withDefaultValue(0) def add(s: String): Unit = count
假设我想在
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和更新不是以原子方式发生的. Concurrent maps添加a few atomic operations到可变地图API,但不是我需要的,这将看起来像这样: def replace(k: A,f: B => B): Option[B] 我知道我可以使用ScalaSTM的 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 } } 但是(现在)仍然是一个额外的依赖.其他选项将包括actors(另一个依赖关系),同步(可能较不有效)或Java的atomic references(less idiomatic). 一般来说,我会避免Scala中的可变地图,但我偶尔需要这样的事情,最近我使用了STM方法(而不是只是穿过我的手指,希望我不会被天真的咬伤解). 我知道这里有一些折中(额外的依赖关系,而不是性能与清晰度等),但是在Scala 2.10中有什么像“正确”的这个问题的答案? 解决方法
这个怎么样?假设你现在真的不需要一般的替代方法,只是一个柜台.
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.atomic.AtomicInteger object CountedMap { private val counts = new ConcurrentHashMap[String,AtomicInteger] def add(key: String): Int = { val zero = new AtomicInteger(0) val value = Option(counts.putIfAbsent(key,zero)).getOrElse(zero) value.incrementAndGet } } 你可以在整个地图上比同步更好的表现,而且你也得到原子增量. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |