Scala同步最佳实践

Ant*_*and 1 multithreading scala

我开始学习Scala和Akka作为演员模型.例如,在像C这样的命令式语言中,我可以使用几种不同的方法来同步线程,例如二叉树; 简单的信号量或互斥量,原子操作等等.

然而,Scala是一种功能面向对象的语言,它可以利用Akka库(例如)实现一个actor模型.如何在Scala中实现同步?假设我有二进制树,我的程序假设遍历并执行不同的操作.我应该如何确保两个不同的演员不是,例如,同时删除同一个节点?

Ric*_*ose 8

如果要对数据结构进行同步访问,只需使用同步块的synchronized方法AnyRef即可.例如:

object Test {
  private val myMap = collection.mutable.Map.empty[Int, Int]
  def set(key: Int, value: Int): Unit = synchronized { myMap(key) = value }
  def get(key: Int): Option[Int] = synchronized { myMap.get(key) }
}
Run Code Online (Sandbox Code Playgroud)

但是,使用actor的目的是避免线程相互阻塞,这会损害可伸缩性.管理可变状态的Actor方式是将状态设置为Actor实例的私有状态,并且仅响应消息而更新或访问.这是一个更复杂的设计,如:

// define case classes Get, Set, Value here.
class MapHolderActor extends Actor {
  private val myMap = collection.mutable.Map.empty[Int, Int] 
  def receive {
    case Get(key) => sender ! Value(myMap.get(key))
    case Set(key, value) => myMap(key) = value
  }
}
Run Code Online (Sandbox Code Playgroud)


om-*_*nom 5

  1. 在较高的层次上,您可以将Actor用作互斥锁:它将逐个处理所有传入的消息.
  2. 在较低级别(但不是在actor级别),没有什么能阻止你使用普通的旧Java并发原语
  3. 使用不可变数据结构,如@Tanmay所提议的那样,因此不存在就地修改,因此没有数据竞争
  4. 交易者(虽然在最近的akka​​版本中已被弃用)