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
中)。在这两种情况下,globalOne
和globalTwo
都不会以任何方式"锁定"。此外,只要您不synchronize
"锁定"对象,您仍然可以对"锁定"对象执行任何操作。虽然这没有被明确禁止,但在大多数情况下,这不是你真正想要的。这正是您的代码中发生的情况。您的dosync
通过某个对象同步,但getKey
(尽管很可能是同一this
的一部分)根本不同步,因此可以以不安全的方式访问globalOne
。如果你希望它是安全的 - 你也应该synchronize
里面getKey