我在Scala中同步什么对象?

时间:2013-06-16 03:37:30

标签: java multithreading scala

在C#中,这非常简单:

class Class1{
  private static readonly object locker = new object();
  void Method1(){
    lock(locker) { .... }
  }
}

我绝对不应该在this上进行同步,因为它可能会导致死锁。同样,在Scala中,我看到了一些示例,无法了解同步和对象(字段)的基本原理是什么,我应该使用它来进行同步:

#1
def add(user: User) {
  // tokenizeName was measured to be the most expensive operation.
  val tokens = tokenizeName(user.name)

  tokens.foreach { term =>
    userMap.synchronized {
      add(term, user)
    }
  }
}

#2
class Person(var name: String) {
  def set(changedName: String) {
    this.synchronized {
      name = changedName
    }
  }
}

#3 and so on...

你介意为我说清楚吗?

3 个答案:

答案 0 :(得分:17)

在Scala中,获得相同的行为更为直接(我假设你想要出于某种原因锁定包含的对象,例如比锁定该类的整个实例更精细的控制):

class Class1 {
  private object Locker
  def method1 { Locker.synchronized { ... } }
}

但你应该很少以这种方式控制事物。特别是,它不会阻止C#或Scala中的死锁,而不会引起...的注意。

你至少应该使用java.util.concurrent中的并发工具,你可能想看看期货或演员。

答案 1 :(得分:15)

  1. 在Scala中锁定对象与在Java中对静态字段/类进行锁定相同,这基本上是最难的一个'锁。它将阻止不在类实例上的操作,而是在类加载器范围内的类本身上。在引入这样的锁时你应该仔细考虑。它不会因为获取的锁定顺序错误而保护您免受死锁,而是会导致阻塞线程,如果它们正在处理类的不同实例,并且可能根本不会干扰。

  2. 锁定'这个'或者某些类(非对象)字段(mutex)是更宽松的同步方式,您应该使用它来管理不是类的访问 - 而是使用此类的特定实例。

  3. 看看akka中的演员,他们摇滚并消除了许多同步问题。

  4. 旁注:在'这个'上进行同步并不意味着死锁。

答案 2 :(得分:8)

如果前提是您要避免锁定this,因为具有第三方代码的另一个线程可以锁定同一个对象,则Scala会提供一个更高级别的可见性private[this]

class C {
  private[this] val lock = new Object()
  def method1(): Unit = lock.synchronized {
    println("method1")
  }
}

实际上除了C的特定实例之外,其他任何对象都不能访问lock。即使来自同一班级的其他实例也无法访问lock