Skip to content

Commit c41961c

Browse files
committed
Fix #2275: Fix deadlock in @volatile lazy vals
Apply patch suggested in #2276
1 parent 57f3efb commit c41961c

File tree

3 files changed

+23
-3
lines changed

3 files changed

+23
-3
lines changed

docs/docs/reference/changed/lazy-vals-spec.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class Foo {
5555
LazyVals.wait4Notification(this, bitmap_offset, flag, <field-id>)
5656
case <state-3> =>
5757
retry = false
58-
result = $target
58+
result = value_0
5959
}
6060
}
6161
result

library/src/dotty/runtime/LazyVals.scala

+3-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ object LazyVals {
4343
var retry = true
4444
while (retry) {
4545
val cur = get(t, offset)
46-
if (STATE(cur, ord) == 1) retry = CAS(t, offset, cur, v, ord)
46+
if (STATE(cur, ord) == 1) retry = !CAS(t, offset, cur, v, ord)
4747
else {
4848
// cur == 2, somebody is waiting on monitor
4949
if (CAS(t, offset, cur, v, ord)) {
@@ -67,7 +67,8 @@ object LazyVals {
6767
else if (state == 2) {
6868
val monitor = getMonitor(t, ord)
6969
monitor.synchronized {
70-
monitor.wait()
70+
if (STATE(get(t, offset), ord) == 2) // make sure notification did not happen yet.
71+
monitor.wait()
7172
}
7273
}
7374
else retry = false

tests/run/i2275.scala

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
object Test {
2+
var count = 0
3+
4+
@volatile lazy val x: Int = {
5+
if (count < 100) {
6+
count += 1
7+
???
8+
}
9+
1
10+
}
11+
12+
def main(args: Array[String]): Unit = {
13+
def fetchLazy(): Unit = try x catch { case _: Throwable => fetchLazy() }
14+
15+
for (_ <- 0 until 10) {
16+
new Thread(() => fetchLazy()).start()
17+
}
18+
}
19+
}

0 commit comments

Comments
 (0)