在 Scala 中,同步块是否锁定了块中访问的所有全局变量?


import scala.collection.immutable.HashMap
class MyClass {
var globalOne = HashMap[String, String]()
var globalTwo = HashMap[String, String]()
def dosync(k:String, v:String) = {
synchronized {
globalOne = globalOne.updated(k, v)
globalTwo = globalTwo.updated(k, v)
}
}
def getKey(k:String) = {
globalOne.get(k)
}
}
当"dosync">

被执行时,"getKey"被阻止了吗,因为dosync正在访问getKey正在访问的全局变量?

简短的回答是:不。此外,它根本不锁定任何全局变量。

不幸的是,Scala文档在这个主题上不是很丰富,但你可以参考Java文档同步,因为它实际上是一回事。根据 Scala 规范,synchronized来自

class AnyRef extends Any {
...
def synchronized[T](body: => T): T // execute `body` in while locking `this`.
}

这意味着您的

def dosync(k: SomeType, v: OtherType):Unit = {
synchronized {
globalOne = globalOne.put(k, v)
globalTwo = globalTwo.put(k, v)
}
}

被翻译成Java与

public void dosync(SomeType k, OtherType v) {
synchronized(this) {
globalOne = globalOne.put(k, v)
globalTwo = globalTwo.put(k, v)
}
}

这里的关键问题是:在这种情况下this什么?它要么是类的实例,其中dosync,要么是静态Class对象(如果dosync位于简单object中)。在这两种情况下,globalOneglobalTwo都不会以任何方式"锁定"。此外,只要您不synchronize"锁定"对象,您仍然可以对"锁定"对象执行任何操作。虽然这没有被明确禁止,但在大多数情况下,这不是你真正想要的。这正是您的代码中发生的情况。您的dosync通过某个对象同步,但getKey(尽管很可能是同一this的一部分)根本不同步,因此可以以不安全的方式访问globalOne。如果你希望它是安全的 - 你也应该synchronize里面getKey

最新更新