15

在 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...

你介意给我说清楚吗?

4

3 回答 3

19

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

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

但是你应该很少以这种方式控制事情。特别是,如果不关注....

您至少应该使用 中的并发工具java.util.concurrent,并且您可能想要研究期货或参与者。

于 2013-06-16T09:16:46.510 回答
16
  1. 在 Scala 中锁定对象与在 Java 中锁定静态字段/类相同,这基本上是“最难”的锁定之一。它不会阻止对类实例的操作,而是在类加载器范围内对类本身进行操作。在引入这样的锁时,您应该仔细考虑。由于获取的锁的顺序不正确,它不会保护您免受死锁的影响,而是会导致线程阻塞,如果线程正在处理类的不同实例,并且可能根本不会干扰。

  2. 锁定“this”或某个类(非对象)字段(互斥锁)是更轻松的同步方式,您应该使用它来管理对类的访问,而不是对此类的特定实例的访问。

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

旁注:在“this”上进行同步并不意味着死锁。

于 2013-06-16T04:11:54.113 回答
9

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

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

这里实际上除了特定实例之外没有其他对象C可以访问lock。甚至同一类的其他实例也无法访问lock.

于 2013-06-16T15:16:49.290 回答