我在Scala中同步什么对象?

在C#中它非常简单:

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

我绝对不应该对此进行同步,因为它可能会导致死锁。 同样,在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... 

你介意给我说清楚吗?

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

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

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

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

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

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

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

您至少应该使用java.util.concurrent的并发工具,并且您可能希望查看期货或演员。

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

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

实际上,除了特定的C实例之外,没有其他对象可以访问lock 。 即使来自同一类的其他实例也无法访问lock