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

时间:2018-01-02 06:37:26

标签: scala concurrency

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)
    }
}

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

1 个答案:

答案 0 :(得分:2)

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

不幸的是,Scala文档在这个主题上并不是很丰富,但您可以参考Java documentation on synchronized,因为它实际上是相同的。根据{{​​3}},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办法。如果您希望它安全 - 您应该synchronizegetKey