如何处理对Scala集合的并发访问?

时间:2011-11-24 11:02:09

标签: scala collections concurrency

我有一个演员 - 从本质上讲 - 维护一个对象列表。它有三个基本操作,一个是添加,更新和删除(有时删除是从add方法调用的,但除此之外),并且可以使用单个集合。显然,后备列表是同时访问的,添加和删除调用会不断相互交错。

我的第一个版本使用了ListBuffer,但是我在某个地方读到它并不意味着并发访问。我没有获得并发访问异常,但我确实注意到了&从中删除对象并不总是有效,可能是由于并发。

我中途重写它以使用var List,但是从Scala的默认不可变List中删除项目有点痛苦 - 我怀疑它适合并发访问。

所以,基本问题:我应该在并发访问情况下使用哪种集合类型,以及如何使用它?

(也许是次要的:一个Actor实际上是一个多线程实体,还是只是我的错误概念,它是否在一个线程中一次处理一个消息?)

(第三级:在Scala中,哪种集合类型最适合插入和随机访问(删除/更新)?)

编辑:对于那些响应者:请原谅我迟到的回复,我在SO或邮件列表上倾倒问题,然后继续讨论下一个问题,暂时忘记原来的问题,这是一个讨厌的习惯。< / p>

4 个答案:

答案 0 :(得分:9)

查看scala.collection.mutable.Synchronized * traits / classes。

我们的想法是将Synchronized traits混合到常规可变集合中以获得它们的同步版本。

例如:

import scala.collection.mutable._
val syncSet = new HashSet[Int] with SynchronizedSet[Int]
val syncArray = new ArrayBuffer[Int] with SynchronizedBuffer[Int]

答案 1 :(得分:5)

您无需同步actor的状态。演员的目的是避免棘手,容易出错并且难以调试并发编程。

Actor模型将确保actor将逐个使用消息,并且对于同一个Actor,您将永远不会有两个消息消息消息。

答案 2 :(得分:4)

Scala的不可变集合适合并发使用。

对于演员来说,有一些事情可以保证,正如Akka文档here所解释的那样。

  • 演员发送规则:在收到同一个演员之前发送消息给演员。
  • 演员后续处理规则:在同一演员处理下一条消息之前,处理一条消息。

您不能保证同一个线程处理下一条消息,但 保证当前消息在下一条消息开始之前完成处理,并且在任何给定时间,只有一条线程正在执行接收方法。

这样可以处理给定Actor的持久状态。关于共享数据,我理解的最好方法是使用不可变数据结构并尽可能地依赖于Actor模型。也就是说,“不要通过共享内存进行通信;通过通信共享内存。”

答案 3 :(得分:-1)

  

我应该在并发访问情况下使用哪种集合类型,以及如何使用它?

请参阅@ hbatista的回答。

  

一个Actor实际上是一个多线程实体,还是只是我错误的概念,并且它在一个线程中一次处理一个消息

第二个(虽然处理消息的线程可能会发生变化,因此不要在线程本地数据中存储任何内容)。这就是演员如何在其状态下保持不变量。