gpt4 book ai didi

scala - 线程安全地变换可变映射中的值

转载 作者:行者123 更新时间:2023-12-01 15:32:36 25 4
gpt4 key购买 nike

假设我想在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
}

不幸的是,这不是线程安全的,因为 getupdate并不是原子发生的。

Concurrent mapsa few atomic operations添加到可变 map 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的 atomic references( less idiomatic)。

总的来说,我会避免在Scala中使用可变的 map ,但是我偶尔会需要这种东西,最近我使用了STM方法(而不是仅仅用手指指望并且不要被幼稚的人所咬伤)。解决方案)。

我知道这里有很多折衷(额外的依赖性,性能,清晰度等),但是在Scala 2.10中是否有类似“正确”的解决方案?

最佳答案

这个怎么样?假设您现在真的不需要通用的replace方法,只需一个计数器即可。

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
}
}

与在整个 map 上进行同步相比,您获得了更好的性能,并且还获得了原子增量。

关于scala - 线程安全地变换可变映射中的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18149133/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com