加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

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

但是(现在)仍然是一个额外的依赖.其他选项将包括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
  }
}

你可以在整个地图上比同步更好的表现,而且你也得到原子增量.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读