Issue unique ticket numbers from multiple threads with AtomicInteger.

atomic update Atomic types make a read-modify-write operation indivisible, so each thread receives a distinct ticket number.

Atomic Ticket

start
AtomicTicket.kt
Replay: real traced execution (multi-file project)
import java.util.concurrent.atomic.AtomicInteger

fun issueTicket(next: AtomicInteger, issued: MutableList<Int>, lock: Any) {
    val ticket = next.getAndIncrement()
    synchronized(lock) {
        issued.add(ticket)
    }
}

fun main() {
    val start = 40
    val next = AtomicInteger(start)
    val issued = mutableListOf<Int>()
    val lock = Any()

    val first = Thread { issueTicket(next, issued, lock) }
    val second = Thread { issueTicket(next, issued, lock) }

    first.start()
    second.start()
    first.join()
    second.join()

    issued.sort()
    println("start=$start")
    println("issued=${issued.joinToString(",")}")
}
import java.util.concurrent.atomic.AtomicInteger

fun issueTicket(next: AtomicInteger, issued: MutableList<Int>, lock: Any) {
    val ticket = next.getAndIncrement()
    synchronized(lock) {
        issued.add(ticket)
    }
}

fun main() {
    val start = 10
    val next = AtomicInteger(start)
    val issued = mutableListOf<Int>()
    val lock = Any()

    val first = Thread { issueTicket(next, issued, lock) }
    val second = Thread { issueTicket(next, issued, lock) }

    first.start()
    second.start()
    first.join()
    second.join()

    issued.sort()
    println("start=$start")
    println("issued=${issued.joinToString(",")}")
}
import java.util.concurrent.atomic.AtomicInteger

fun issueTicket(next: AtomicInteger, issued: MutableList<Int>, lock: Any) {
    val ticket = next.getAndIncrement()
    synchronized(lock) {
        issued.add(ticket)
    }
}

fun main() {
    val start = 100
    val next = AtomicInteger(start)
    val issued = mutableListOf<Int>()
    val lock = Any()

    val first = Thread { issueTicket(next, issued, lock) }
    val second = Thread { issueTicket(next, issued, lock) }

    first.start()
    second.start()
    first.join()
    second.join()

    issued.sort()
    println("start=$start")
    println("issued=${issued.joinToString(",")}")
}
  1. start ← 40, next ← 40, issued ← [], lock ← ⟨Object A⟩, first ← Thread[#19,Thread-0,5,main]

    10fun main() {11    val start→ 40 = 40 //@start=10, 10012    val next→ 40 = AtomicInteger(start40)13    val issued→ [] = mutableListOf<Int>()14    val lock→ ⟨Object A⟩ = Any()1516    val first→ Thread[#19,Thread-0,5,main] = Thread { issueTicket(next, issued, lock) }17    val second→ Thread[#20,Thread-1,5,main] = Thread { issueTicket(next, issued, lock) }1819    firstThread[#19,Thread-0,5,main].start()20    secondThread[#20,Thread-1,5,main].start()21    first.join()
  2. fun issueTicket(next: AtomicInteger, issued: MutableList<Int>, lock: A…

    pass 1 of 2
    3fun issueTicket(next40: AtomicInteger, issued[]: MutableList<Int>, lock⟨Object A⟩: Any) {4    val ticket = next.getAndIncrement()
  3. fun issueTicket(next: AtomicInteger, issued: MutableList<Int>, lock: A…

    pass 2 of 2
    3fun issueTicket(next40: AtomicInteger, issued[]: MutableList<Int>, lock⟨Object A⟩: Any) {4    val ticket = next.getAndIncrement()
  4. next ← 41, ticket ← 40

    3fun issueTicket(next: AtomicInteger, issued: MutableList<Int>, lock: Any) {4    val ticket→ 40 = next→ 41.getAndIncrement()5    synchronized(lock⟨Object A⟩) {6        issued.add(ticket)7    }8}910fun main() {11    val start = 40 //@start=10, 10012    val next = AtomicInteger(start)13    val issued = mutableListOf<Int>()14    val lock = Any()1516    val first = Thread { issueTicket(next, issued, lock) }17    val second = Thread { issueTicket(next, issued, lock) }1819    first.start()20    secondThread[#20,Thread-1,5,main].start()21    firstThread[#19,Thread-0,5,main].join()22    second.join()
  5. next ← 42, ticket ← 41

    pass 1 of 2
    3fun issueTicket(next: AtomicInteger, issued: MutableList<Int>, lock: Any) {4    val ticket→ 41 = next→ 42.getAndIncrement()5    synchronized(lock⟨Object A⟩) {6        issued.add(ticket)7    }8}
  6. pass 2 of 2
    4val ticket = next.getAndIncrement()5synchronized(lock) {6    issued.add(ticket)7}
  7. first ← Thread[#19,Thread-0,5,]

    20    second.start()21    first→ Thread[#19,Thread-0,5,].join()22    secondThread[#20,Thread-1,5,].join()2324    issued[40, 41].sort()25    println("start=$start40")26    println("issued=${issued[40, 41].joinToString(",")}")27}
    outputstart=40
    issued=40,41
  1. start ← 10, next ← 10, issued ← [], lock ← ⟨Object A⟩, first ← Thread[#19,Thread-0,5,main]

    10fun main() {11    val start→ 10 = 1012    val next→ 10 = AtomicInteger(start10)13    val issued→ [] = mutableListOf<Int>()14    val lock→ ⟨Object A⟩ = Any()1516    val first→ Thread[#19,Thread-0,5,main] = Thread { issueTicket(next, issued, lock) }17    val second→ Thread[#20,Thread-1,5,main] = Thread { issueTicket(next, issued, lock) }1819    firstThread[#19,Thread-0,5,main].start()20    secondThread[#20,Thread-1,5,main].start()21    first.join()
  2. fun issueTicket(next: AtomicInteger, issued: MutableList<Int>, lock: A…

    pass 1 of 2
    3fun issueTicket(next10: AtomicInteger, issued[]: MutableList<Int>, lock⟨Object A⟩: Any) {4    val ticket = next.getAndIncrement()
  3. fun issueTicket(next: AtomicInteger, issued: MutableList<Int>, lock: A…

    pass 2 of 2
    3fun issueTicket(next10: AtomicInteger, issued[]: MutableList<Int>, lock⟨Object A⟩: Any) {4    val ticket = next10.getAndIncrement()5    synchronized(lock) {
  4. next ← 11, ticket ← 10

    3fun issueTicket(next: AtomicInteger, issued: MutableList<Int>, lock: Any) {4    val ticket→ 10 = next→ 11.getAndIncrement()5    synchronized(lock⟨Object A⟩) {6        issued.add(ticket)7    }8}910fun main() {11    val start = 1012    val next = AtomicInteger(start)13    val issued = mutableListOf<Int>()14    val lock = Any()1516    val first = Thread { issueTicket(next, issued, lock) }17    val second = Thread { issueTicket(next, issued, lock) }1819    first.start()20    secondThread[#20,Thread-1,5,main].start()21    firstThread[#19,Thread-0,5,main].join()22    second.join()
  5. next ← 12, ticket ← 11

    pass 1 of 2
    3fun issueTicket(next: AtomicInteger, issued: MutableList<Int>, lock: Any) {4    val ticket→ 11 = next→ 12.getAndIncrement()5    synchronized(lock⟨Object A⟩) {6        issued.add(ticket)7    }8}
  6. pass 2 of 2
    4val ticket = next.getAndIncrement()5synchronized(lock) {6    issued.add(ticket)7}
  7. first ← Thread[#19,Thread-0,5,]

    20    second.start()21    first→ Thread[#19,Thread-0,5,].join()22    secondThread[#20,Thread-1,5,].join()2324    issued[10, 11].sort()25    println("start=$start10")26    println("issued=${issued[10, 11].joinToString(",")}")27}
    outputstart=10
    issued=10,11
  1. start ← 100, next ← 100, issued ← [], lock ← ⟨Object A⟩, first ← Thread[#19,Thread-0,5,main]

    10fun main() {11    val start→ 100 = 10012    val next→ 100 = AtomicInteger(start100)13    val issued→ [] = mutableListOf<Int>()14    val lock→ ⟨Object A⟩ = Any()1516    val first→ Thread[#19,Thread-0,5,main] = Thread { issueTicket(next, issued, lock) }17    val second→ Thread[#20,Thread-1,5,main] = Thread { issueTicket(next, issued, lock) }1819    firstThread[#19,Thread-0,5,main].start()20    secondThread[#20,Thread-1,5,main].start()21    first.join()
  2. fun issueTicket(next: AtomicInteger, issued: MutableList<Int>, lock: A…

    pass 1 of 2
    3fun issueTicket(next100: AtomicInteger, issued[]: MutableList<Int>, lock⟨Object A⟩: Any) {4    val ticket = next.getAndIncrement()
  3. second.start()

    19first.start()20secondThread[#20,Thread-1,5,main].start()21first.join()
  4. fun issueTicket(next: AtomicInteger, issued: MutableList<Int>, lock: A…

    pass 2 of 2
    3fun issueTicket(next100: AtomicInteger, issued[]: MutableList<Int>, lock⟨Object A⟩: Any) {4    val ticket = next100.getAndIncrement()5    synchronized(lock) {
  5. next ← 102, ticket ← 101

    3fun issueTicket(next: AtomicInteger, issued: MutableList<Int>, lock: Any) {4    val ticket→ 101 = next→ 102.getAndIncrement()5    synchronized(lock⟨Object A⟩) {6        issued.add(ticket)7    }8}910fun main() {11    val start = 10012    val next = AtomicInteger(start)13    val issued = mutableListOf<Int>()14    val lock = Any()1516    val first = Thread { issueTicket(next, issued, lock) }17    val second = Thread { issueTicket(next, issued, lock) }1819    first.start()20    second.start()21    firstThread[#19,Thread-0,5,main].join()22    second.join()
  6. pass 1 of 2
    4    val ticket = next.getAndIncrement()5    synchronized(lock⟨Object A⟩) {6        issued.add(ticket)7    }8}
  7. pass 2 of 2
    4val ticket = next.getAndIncrement()5synchronized(lock) {6    issued.add(ticket)7}
  8. first ← Thread[#19,Thread-0,5,]

    20    second.start()21    first→ Thread[#19,Thread-0,5,].join()22    secondThread[#20,Thread-1,5,].join()2324    issued[100, 101].sort()25    println("start=$start100")26    println("issued=${issued[100, 101].joinToString(",")}")27}
    outputstart=100
    issued=100,101