仅当在 Scala 中使用不相关的对象时,块才会同步
Block is synchronised only when using unrelated object in Scala
我有一个函数 getUniqueId
试图在每次调用时 return 一个唯一的 ID。
private var uidCount = 0L
def getUniqueId() = uidCount.synchronized {
uidCount = uidCount + 1
uidCount
}
它的定义在 Long
变量 uidCount
上同步。
我们正在使用另一个函数调用此函数 startThread
。
def startThread() = {
val t = new Thread {
override def run() = {
val uids = for (i <- 0 until 10) yield getUniqueId()
println(uids)
}
}
t.start
}
因此,对于每个函数调用,理想情况下我们应该在控制台上看到 10 个唯一 ID。
我们使用多线程调用 ID,如下所示:
startThread(); startThread(); startThread()
但是我得到了带有重复 ID 的输出:
输出:
Vector(7, 11, 13, 16, 22, 24, 25, 26, 27, 28)
Vector(2, 6, 8, 9, 12, 14, 17, 19, 21, 23)
Vector(1, 3, 4, 5, 8, 10, 12, 15, 18, 20)
这里我们可以看到8和12是重复的
类似地,如果我在 Class AnyRef
的随机对象上同步 getUniqueId()
。
即我将定义更改为:
private var uidCount = 0L
private var x = new AnyRef
def getUniqueId() = x.synchronized {
uidCount = uidCount + 1
uidCount
}
然后突然之间 getUniqueId 是原子的。输出总是类似于:
Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
Vector(11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
Vector(21, 22, 23, 24, 25, 26, 27, 28, 29, 30)
即没有重复。
有人可以解释为什么我不能使用 uidCount
使 getUniqueId
原子化吗?
uidCount
是一个随时都在变化的原始变量
每次调用 getUniqueId
时,都会围绕原始值创建一个新的包装器。在每次进入方法体时都重新创建的新对象上同步没有任何意义:与该对象关联的内在锁将始终恰好获取一次,然后立即释放,包装对象将被丢弃.
我有一个函数 getUniqueId
试图在每次调用时 return 一个唯一的 ID。
private var uidCount = 0L
def getUniqueId() = uidCount.synchronized {
uidCount = uidCount + 1
uidCount
}
它的定义在 Long
变量 uidCount
上同步。
我们正在使用另一个函数调用此函数 startThread
。
def startThread() = {
val t = new Thread {
override def run() = {
val uids = for (i <- 0 until 10) yield getUniqueId()
println(uids)
}
}
t.start
}
因此,对于每个函数调用,理想情况下我们应该在控制台上看到 10 个唯一 ID。
我们使用多线程调用 ID,如下所示:
startThread(); startThread(); startThread()
但是我得到了带有重复 ID 的输出: 输出:
Vector(7, 11, 13, 16, 22, 24, 25, 26, 27, 28)
Vector(2, 6, 8, 9, 12, 14, 17, 19, 21, 23)
Vector(1, 3, 4, 5, 8, 10, 12, 15, 18, 20)
这里我们可以看到8和12是重复的
类似地,如果我在 Class AnyRef
的随机对象上同步 getUniqueId()
。
即我将定义更改为:
private var uidCount = 0L
private var x = new AnyRef
def getUniqueId() = x.synchronized {
uidCount = uidCount + 1
uidCount
}
然后突然之间 getUniqueId 是原子的。输出总是类似于:
Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
Vector(11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
Vector(21, 22, 23, 24, 25, 26, 27, 28, 29, 30)
即没有重复。
有人可以解释为什么我不能使用 uidCount
使 getUniqueId
原子化吗?
uidCount
是一个随时都在变化的原始变量
每次调用 getUniqueId
时,都会围绕原始值创建一个新的包装器。在每次进入方法体时都重新创建的新对象上同步没有任何意义:与该对象关联的内在锁将始终恰好获取一次,然后立即释放,包装对象将被丢弃.