nai*_*rbv 6 multithreading functional-programming scala actor
我被告知(Scala)Actors实际上从不实际执行两个操作,这表明该行为(或反应?或接收?)方法本质上是同步的.我知道一个act方法中的长操作会导致阻塞问题,我认为必须以某种方式同步对消息队列的访问......但是......
建议的是,接收消息告诉它增加内部计数器的actor将以线程安全的方式递增计数器.不会同时处理两条更新消息,因此没有两条消息可以同时尝试更新计数器.
演员中的计数器属性听起来像"共享状态".
这样的操作是完全线程安全的吗?如果是这样,演员如何以一种有效的方式使用多个核心机器?演员如何多线程?
如果没有,那么以线程安全方式计算消息而不需要某些synchronized/volatile变量的适当惯用方法是什么?
Actor模型可用于将可变状态与外界隔离.当您具有可变状态(例如,分配给多个并发进程的ID的全局注册表)时,您可以将该可变状态包装在Actor内部并使客户端通过消息传递与Actor通信.这样只有actor直接访问可变状态,正如你所说,客户端消息排队等待逐个读取和处理.消息是不可变的很重要.
为了避免队列变满,重要的是,所述消息处理(react,receive等)是尽可能的短.长期运行的任务应交给其他演员:
1. Actor A receives a message M from sender S
2. A spawns a new actor C
3. A sends (S, f(M)) to C
4. In parallel:
4a. A starts processing the next message.
4b. C does the long-running or dangerous (IO) task,
When finished, sends the result to S,
and C terminates.
Run Code Online (Sandbox Code Playgroud)
该过程中的一些替代方案:
(S, result)回给A,后者转发给S.ActorRef C => (Sender S, Message M) 以便在看到C失败时,它可以使用新的Actor重试处理M.所以回顾一下,一个Actor是多线程的,多个客户端可以从各个线程发送多个消息,并保证Actor将串行处理所有这些消息(尽管排序可能受到各种非过度的影响)严格约束).
请注意,虽然Actor的react代码可以在各种线程上执行,但是在一个给定的时间点它只在一个给定的线程上执行(你可以想象一下,当调度程序认为合适时,Actor会从一个线程跳转到另一个线程,但是这个是一个技术细节).注意:内部状态仍然不需要同步,因为Actors 保证在处理消息之间的语义之前发生.
并行性是通过让多个Actors并行工作来实现的,通常形成管理层次结构或平衡工作负载.
请注意,如果您只需要并发/异步计算,但是您没有或可以摆脱全局状态,那么Futures是一个更好的组合和更容易的概念.
"演员"不是多线程的,但演员系统通常是.每个actor一次只执行一个动作,但是当有多个actor时,每个actor可以并行地在其各自的封装状态下操作.如果不在actor之间共享,则counter属性不是共享可变状态.
如果您的问题是关于actor系统的实现,那么它可以变化并且通常是可配置的,即默认的Scala actor可以配置为运行单线程或线程池或使用Java ForkJoin任务.我发现scala.actors源代码非常易读,所以如果你想了解发生了什么,我建议看看.