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 documentation on synchronized因为它实际上是同一件事。根据Scala spec , 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
在简单的 object
中,它可以是 dosync
所在类的实例或静态 Class
对象。在这两种情况下,globalOne
和 globalTwo
都没有以任何方式“锁定”。此外,只要您不对该对象进行同步
,您仍然可以对该对象做任何您想做的事情。虽然这没有被明确禁止,但在大多数情况下,这并不是您真正想要的。这正是您的代码中发生的情况。您的 dosync
已在某个对象上同步,但 getKey
(尽管很可能是同一 this
的一部分)根本不同步,因此可以以不安全的方式访问 globalOne
。如果你希望它是安全的——你也应该在 getKey
中 synchronize
关于scala - 在 Scala 中,synchronized block 是否锁定 block 中访问的所有全局变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48056564/