Concurrency and Source Panels
Atomic Ticket
Issue unique ticket numbers from two threads with AtomicInteger.
atomic-update
Atomic types make a read-modify-write operation indivisible, so each thread receives a distinct ticket number.
Atomic Ticket
AtomicTicket.scala
Replay: real traced execution (multi-file project)
import java.util.concurrent.atomic.AtomicInteger
object Main {
val next = new AtomicInteger(0)
var firstTicket = 0
var secondTicket = 0
def firstWork(): Unit = {
firstTicket = next.getAndIncrement()
}
def secondWork(): Unit = {
secondTicket = next.getAndIncrement()
}
def main(args: Array[String]): Unit = {
val start = 40
next.set(start)
val first = Thread(() => firstWork())
val second = Thread(() => secondWork())
first.start()
second.start()
first.join()
second.join()
val low = Math.min(firstTicket, secondTicket)
val high = Math.max(firstTicket, secondTicket)
println("start=" + start)
println("tickets=" + low + "," + high)
}
}
import java.util.concurrent.atomic.AtomicInteger
object Main {
val next = new AtomicInteger(0)
var firstTicket = 0
var secondTicket = 0
def firstWork(): Unit = {
firstTicket = next.getAndIncrement()
}
def secondWork(): Unit = {
secondTicket = next.getAndIncrement()
}
def main(args: Array[String]): Unit = {
val start = 10
next.set(start)
val first = Thread(() => firstWork())
val second = Thread(() => secondWork())
first.start()
second.start()
first.join()
second.join()
val low = Math.min(firstTicket, secondTicket)
val high = Math.max(firstTicket, secondTicket)
println("start=" + start)
println("tickets=" + low + "," + high)
}
}
import java.util.concurrent.atomic.AtomicInteger
object Main {
val next = new AtomicInteger(0)
var firstTicket = 0
var secondTicket = 0
def firstWork(): Unit = {
firstTicket = next.getAndIncrement()
}
def secondWork(): Unit = {
secondTicket = next.getAndIncrement()
}
def main(args: Array[String]): Unit = {
val start = 100
next.set(start)
val first = Thread(() => firstWork())
val second = Thread(() => secondWork())
first.start()
second.start()
first.join()
second.join()
val low = Math.min(firstTicket, secondTicket)
val high = Math.max(firstTicket, secondTicket)
println("start=" + start)
println("tickets=" + low + "," + high)
}
}
start ← 40, next ← 40, first ← Thread[#19,Thread-0,5,main], second ← Thread[#20,Thread-1,5,main]
16def main(args: Array[String]): Unit = {17 val start→ 40 = 40 //@start=10, 10018 next→ 40.set(start40)1920 val first→ Thread[#19,Thread-0,5,main] = Thread(() => firstWork())21 val second→ Thread[#20,Thread-1,5,main] = Thread(() => secondWork())2223 firstThread[#19,Thread-0,5,main].start()24 second.start()25 first.join()first.start()
8def firstWork(): Unit = {9 firstTicket = next40.getAndIncrement()10}1112def secondWork(): Unit = {13 secondTicket = next.getAndIncrement()14}1516def main(args: Array[String]): Unit = {17 val start = 40 //@start=10, 10018 next.set(start)1920 val first = Thread(() => firstWork())21 val second = Thread(() => secondWork())2223 firstThread[#19,Thread-0,5,main].start()24 secondThread[#20,Thread-1,5,main].start()25 first.join()26 second.join()low ← 40, high ← 41
12 def secondWork(): Unit = {13 secondTicket = next41.getAndIncrement()14 }1516 def main(args: Array[String]): Unit = {17 val start = 40 //@start=10, 10018 next.set(start)1920 val first = Thread(() => firstWork())21 val second = Thread(() => secondWork())2223 first.start()24 secondThread[#20,Thread-1,5,main].start()25 firstThread[#19,Thread-0,5,].join()26 secondThread[#20,Thread-1,5,].join()2728 val low→ 40 = Math.min(firstTicket40, secondTicket41)29 val high→ 41 = Math.max(firstTicket40, secondTicket41)30 println("start=" + start40)31 println("tickets=" + low40 + "," + high41)32 }33}outputstart=40 tickets=40,41
start ← 10, next ← 10, first ← Thread[#19,Thread-0,5,main], second ← Thread[#20,Thread-1,5,main]
16def main(args: Array[String]): Unit = {17 val start→ 10 = 1018 next→ 10.set(start10)1920 val first→ Thread[#19,Thread-0,5,main] = Thread(() => firstWork())21 val second→ Thread[#20,Thread-1,5,main] = Thread(() => secondWork())2223 firstThread[#19,Thread-0,5,main].start()24 second.start()25 first.join()first.start()
8def firstWork(): Unit = {9 firstTicket = next10.getAndIncrement()10}1112def secondWork(): Unit = {13 secondTicket = next.getAndIncrement()14}1516def main(args: Array[String]): Unit = {17 val start = 1018 next.set(start)1920 val first = Thread(() => firstWork())21 val second = Thread(() => secondWork())2223 firstThread[#19,Thread-0,5,main].start()24 secondThread[#20,Thread-1,5,main].start()25 first.join()26 second.join()low ← 10, high ← 11
12 def secondWork(): Unit = {13 secondTicket = next11.getAndIncrement()14 }1516 def main(args: Array[String]): Unit = {17 val start = 1018 next.set(start)1920 val first = Thread(() => firstWork())21 val second = Thread(() => secondWork())2223 first.start()24 secondThread[#20,Thread-1,5,main].start()25 firstThread[#19,Thread-0,5,].join()26 secondThread[#20,Thread-1,5,].join()2728 val low→ 10 = Math.min(firstTicket10, secondTicket11)29 val high→ 11 = Math.max(firstTicket10, secondTicket11)30 println("start=" + start10)31 println("tickets=" + low10 + "," + high11)32 }33}outputstart=10 tickets=10,11
start ← 100, next ← 100, first ← Thread[#19,Thread-0,5,main], second ← Thread[#20,Thread-1,5,main]
16def main(args: Array[String]): Unit = {17 val start→ 100 = 10018 next→ 100.set(start100)1920 val first→ Thread[#19,Thread-0,5,main] = Thread(() => firstWork())21 val second→ Thread[#20,Thread-1,5,main] = Thread(() => secondWork())2223 firstThread[#19,Thread-0,5,main].start()24 second.start()25 first.join()def firstWork(): Unit =
8def firstWork(): Unit = {9 firstTicket = next100.getAndIncrement()10}first ← Thread[#19,Thread-0,5,]
23first→ Thread[#19,Thread-0,5,].start()24secondThread[#20,Thread-1,5,main].start()25first.join()26second.join()def secondWork(): Unit =
12def secondWork(): Unit = {13 secondTicket = next101.getAndIncrement()14}second ← Thread[#20,Thread-1,5,], low ← 100, high ← 101
23 first.start()24 second→ Thread[#20,Thread-1,5,].start()25 firstThread[#19,Thread-0,5,].join()26 secondThread[#20,Thread-1,5,].join()2728 val low→ 100 = Math.min(firstTicket100, secondTicket101)29 val high→ 101 = Math.max(firstTicket100, secondTicket101)30 println("start=" + start100)31 println("tickets=" + low100 + "," + high101)32 }33}outputstart=100 tickets=100,101