如何处理对 Scala 集合的并发访问?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8255991/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to handle concurrent access to a Scala collection?
提问by fwielstra
I have an Actor that - in its very essence - maintains a list of objects. It has three basic operations, an add, update and a remove (where sometimes the remove is called from the add method, but that aside), and works with a single collection. Obviously, that backing list is accessed concurrently, with add and remove calls interleaving each other constantly.
我有一个 Actor - 从本质上讲 - 维护一个对象列表。它具有三个基本操作,添加、更新和删除(有时从 add 方法调用删除,但除此之外),并且使用单个集合。显然,该支持列表是并发访问的,添加和删除调用不断相互交错。
My first version used a ListBuffer, but I read somewhere it's not meant for concurrent access. I haven't gotten concurrent access exceptions, but I did note that finding & removing objects from it does not always work, possibly due to concurrency.
我的第一个版本使用了 ListBuffer,但我在某处读到它不适用于并发访问。我没有遇到并发访问异常,但我确实注意到从中查找和删除对象并不总是有效,可能是由于并发。
I was halfway rewriting it to use a var List, but removing items from Scala's default immutable List is a bit of a pain - and I doubt it's suitable for concurrent access.
我正在中途重写它以使用 var List,但是从 Scala 的默认不可变 List 中删除项目有点痛苦 - 我怀疑它是否适合并发访问。
So, basic question: What collection type should I use in a concurrent access situation, and how is it used?
那么,基本问题是:在并发访问情况下我应该使用什么集合类型,它是如何使用的?
(Perhaps secondary: Is an Actor actually a multithreaded entity, or is that just my wrong conception and does it process messages one at a time in a single thread?)
(也许是次要的:Actor 实际上是一个多线程实体,还是只是我的错误概念,它是否在单个线程中一次处理一条消息?)
(Tertiary: In Scala, what collection type is best for inserts and random access (delete / update)?)
(第三级:在 Scala 中,哪种集合类型最适合插入和随机访问(删除/更新)?)
Edit: To the kind responders: Excuse my late reply, I'm making a nasty habit out of dumping a question on SO or mailing lists, then moving on to the next problem, forgetting the original one for the moment.
编辑:致善意的回复者:请原谅我迟到的回复,我正在养成一个坏习惯,即在 SO 或邮件列表上倾倒问题,然后继续解决下一个问题,暂时忘记原来的问题。
回答by hbatista
Take a look at the scala.collection.mutable.Synchronized* traits/classes.
查看 scala.collection.mutable.Synchronized* 特征/类。
The idea is that you mixin the Synchronized traits into regular mutable collections to get synchronized versions of them.
这个想法是您将 Synchronized 特征混合到常规可变集合中以获得它们的同步版本。
For example:
例如:
import scala.collection.mutable._
val syncSet = new HashSet[Int] with SynchronizedSet[Int]
val syncArray = new ArrayBuffer[Int] with SynchronizedBuffer[Int]
回答by David
You don't need to synchronize the state of the actors. The aim of the actors is to avoid tricky, error prone and hard to debug concurrent programming.
您不需要同步参与者的状态。Actor 的目标是避免棘手、容易出错和难以调试的并发编程。
Actor model will ensure that the actor will consume messages one by one and that you will never have two thread consuming message for the same Actor.
Actor 模型将确保 Actor 将一条一条地消费消息,并且永远不会有两个线程为同一个 Actor 消费消息。
回答by Connor Doyle
Scala's immutable collections are suitable for concurrent usage.
Scala 的不可变集合适合并发使用。
As for actors, a couple of things are guaranteed as explained herethe Akka documentation.
至于演员,作为解释的几件事情是保证这里的阿卡文档。
- the actor send rule: where the send of the message to an actor happens before the receive of the same actor.
- the actor subsequent processing rule: where processing of one message happens before processing of the next message by the same actor.
- 演员发送规则:向演员发送消息发生在同一个演员的接收之前。
- 参与者后续处理规则:其中一条消息的处理发生在同一参与者处理下一条消息之前。
You are not guaranteed that the same thread processes the next message, but you areguaranteed that the current message will finish processing before the next one starts, and also that at any given time, only one thread is executing the receive method.
你不能保证,同样的线程处理的下一条消息,但你是保证当前消息将完成处理下一个开始之前,也即在任何给定的时间,只有一个线程执行接收方法。
So that takes care of a given Actor's persistent state. With regard to shared data, the best approach as I understand it is to use immutable data structures and lean on the Actor model as much as possible. That is, "do not communicate by sharing memory; share memory by communicating."
这样就可以处理给定 Actor 的持久状态。关于共享数据,据我所知,最好的方法是使用不可变的数据结构并尽可能地依赖 Actor 模型。即“不通过共享内存进行通信;通过通信共享内存”。
回答by Alexey Romanov
What collection type should I use in a concurrent access situation, and how is it used?
在并发访问的情况下我应该使用什么集合类型,它是如何使用的?
See @hbatista's answer.
请参阅@hbatista 的回答。
Is an Actor actually a multithreaded entity, or is that just my wrong conception and does it process messages one at a time in a single thread
Actor实际上是一个多线程实体,还是只是我的错误概念,它是否在单个线程中一次处理一个消息
The second (though the thread on which messages are processed may change, so don't store anything in thread-local data). That's how the actor can maintain invariants on its state.
第二个(尽管处理消息的线程可能会改变,所以不要在线程本地数据中存储任何内容)。这就是 actor 可以保持其状态不变的方式。

