scala - 在 Scala 中,synchronized block 是否锁定 block 中访问的所有全局变量?

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

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

关于scala - 在 Scala 中,synchronized block 是否锁定 block 中访问的所有全局变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48056564/

相关文章:

scala - Scala 中的空引用如何合理化?

scala - 使用 SprayJson 编码 java.util.Date

java - ConcurrentHashMap的values()线程安全吗?

c# - 具有基于 XML 的存储的 WCF 服务。并发问题?

java - 仅尝试互联网连接几秒钟

xml - scala 字符串到 scala.xml.Elem

list - 键入要求非空列表的最佳方式是什么(不使用 Scalaz)?

java - 如何在java中获取scala的TypeTag和ClassTag

go - 了解 golang channel 。所有的goroutines都睡着了——死锁【围棋之旅,爬虫】

go - 理解代码 : Sharing resources by communicating