Scala中synchronized块锁定范围及方法阻塞问题咨询
解答Scala synchronized相关的两个问题
问题1:Scala里的synchronized块会锁定块内访问的所有全局变量吗?
当然不会。Scala的synchronized和Java的实现逻辑一致,它锁定的是当前类实例的监视器锁(也就是this对象的锁),而不是块里操作的那些变量本身。
举个例子,你代码里的synchronized块同时操作了globalOne和globalTwo,但线程进入这个块时,只需要获取当前MyClass实例的锁就行——不管你在块里操作多少变量,锁的粒度都是整个对象,不是单个变量。
问题2:执行dosync方法时,getKey会因为访问同一全局变量被阻塞吗?
不会被阻塞。因为getKey方法没有任何同步修饰或者synchronized块,当一个线程拿着MyClass实例的锁执行dosync里的同步逻辑时,另一个线程可以直接调用getKey读取globalOne,完全不会被卡住。
不过这里要提个醒:这种写法有线程安全风险。虽然globalOne是不可变的HashMap,但它被存在var里——dosync的赋值操作是原子的,但没有同步的话,其他线程可能看不到globalOne的最新值(Java内存模型的可见性问题)。如果要保证多线程下的正确性,要么给getKey也加上synchronized,要么用@volatile修饰globalOne和globalTwo,或者直接换成线程安全的可变集合比如java.util.concurrent.ConcurrentHashMap。
你的代码示例
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) } }
内容的提问来源于stack exchange,提问作者N A
相关产品推荐
相关产品推荐

