我有一个演员 - 从本质上讲 - 维护一个对象列表。它有三个基本操作,一个是添加,更新和删除(有时删除是从add方法调用的,但除此之外),并且可以使用单个集合。显然,后备列表是同时访问的,添加和删除调用会不断相互交错。
我的第一个版本使用了ListBuffer,但是我在某个地方读到它并不意味着并发访问。我没有获得并发访问异常,但我确实注意到了&从中删除对象并不总是有效,可能是由于并发。
我中途重写它以使用var List,但是从Scala的默认不可变List中删除项目有点痛苦 - 我怀疑它适合并发访问。
所以,基本问题:我应该在并发访问情况下使用哪种集合类型,以及如何使用它?
(也许是次要的:一个Actor实际上是一个多线程实体,还是只是我的错误概念,它是否在一个线程中一次处理一个消息?)
(第三级:在Scala中,哪种集合类型最适合插入和随机访问(删除/更新)?)
编辑:对于那些响应者:请原谅我迟到的回复,我在SO或邮件列表上倾倒问题,然后继续讨论下一个问题,暂时忘记原来的问题,这是一个讨厌的习惯。< / p>
答案 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实际上是一个多线程实体,还是只是我错误的概念,并且它在一个线程中一次处理一个消息
第二个(虽然处理消息的线程可能会发生变化,因此不要在线程本地数据中存储任何内容)。这就是演员如何在其状态下保持不变量。