Concurrency and Source Panels
Thread Local Context
Give each worker thread its own context value.
thread-local
A `ThreadLocal` stores a value separately for each thread, so worker context can be read without sharing a mutable field.
Thread Local Context
ThreadLocalContext.scala
Replay: real traced execution (multi-file project)
object Main {
val context = new ThreadLocal[String]()
var firstValue = ""
var secondValue = ""
def readAction(name: String, suffix: String, number: Int): Unit = {
context.set(name + "-" + suffix)
firstValue = context.get() + ":" + number
}
def writeAction(name: String, suffix: String, number: Int): Unit = {
context.set(name + "-" + suffix)
secondValue = context.get() + ":" + number
}
def main(args: Array[String]): Unit = {
val suffix = "api"
val reader = Thread(() => readAction("read", suffix, 8))
val writer = Thread(() => writeAction("write", suffix, 9))
reader.start()
writer.start()
reader.join()
writer.join()
println(firstValue)
println(secondValue)
}
}
object Main {
val context = new ThreadLocal[String]()
var firstValue = ""
var secondValue = ""
def readAction(name: String, suffix: String, number: Int): Unit = {
context.set(name + "-" + suffix)
firstValue = context.get() + ":" + number
}
def writeAction(name: String, suffix: String, number: Int): Unit = {
context.set(name + "-" + suffix)
secondValue = context.get() + ":" + number
}
def main(args: Array[String]): Unit = {
val suffix = "db"
val reader = Thread(() => readAction("read", suffix, 8))
val writer = Thread(() => writeAction("write", suffix, 9))
reader.start()
writer.start()
reader.join()
writer.join()
println(firstValue)
println(secondValue)
}
}
object Main {
val context = new ThreadLocal[String]()
var firstValue = ""
var secondValue = ""
def readAction(name: String, suffix: String, number: Int): Unit = {
context.set(name + "-" + suffix)
firstValue = context.get() + ":" + number
}
def writeAction(name: String, suffix: String, number: Int): Unit = {
context.set(name + "-" + suffix)
secondValue = context.get() + ":" + number
}
def main(args: Array[String]): Unit = {
val suffix = "cache"
val reader = Thread(() => readAction("read", suffix, 8))
val writer = Thread(() => writeAction("write", suffix, 9))
reader.start()
writer.start()
reader.join()
writer.join()
println(firstValue)
println(secondValue)
}
}
suffix ← api, reader ← Thread[#19,Thread-0,5,main], writer ← Thread[#20,Thread-1,5,main]
16def main(args: Array[String]): Unit = {17 val suffix→ api = "api" //@suffix="db", "cache"1819 val reader→ Thread[#19,Thread-0,5,main] = Thread(() => readAction("read", suffix, 8))20 val writer→ Thread[#20,Thread-1,5,main] = Thread(() => writeAction("write", suffix, 9))2122 readerThread[#19,Thread-0,5,main].start()23 writerThread[#20,Thread-1,5,main].start()24 reader.join()25 writer.join()def readAction(name: String, suffix: String, number: Int): Unit =
6def readAction(nameread: String, suffixapi: String, number8: Int): Unit = {7 context⟨ThreadLocal A⟩.set(nameread + "-" + suffixapi)8 firstValue = context⟨ThreadLocal A⟩.get() + ":" + number89}writer.start()
22reader.start()23writerThread[#20,Thread-1,5,main].start()24readerThread[#19,Thread-0,5,].join()25writerThread[#20,Thread-1,5,main].join()2627println(firstValue)def writeAction(name: String, suffix: String, number: Int): Unit =
11def writeAction(namewrite: String, suffixapi: String, number9: Int): Unit = {12 context⟨ThreadLocal A⟩.set(namewrite + "-" + suffixapi)13 secondValue = context⟨ThreadLocal A⟩.get() + ":" + number914}writer ← Thread[#20,Thread-1,5,]
24 reader.join()25 writer→ Thread[#20,Thread-1,5,].join()2627 println(firstValueread-api:8)28 println(secondValuewrite-api:9)29 }30}outputread-api:8 write-api:9
suffix ← db, reader ← Thread[#19,Thread-0,5,main], writer ← Thread[#20,Thread-1,5,main]
16def main(args: Array[String]): Unit = {17 val suffix→ db = "db"1819 val reader→ Thread[#19,Thread-0,5,main] = Thread(() => readAction("read", suffix, 8))20 val writer→ Thread[#20,Thread-1,5,main] = Thread(() => writeAction("write", suffix, 9))2122 readerThread[#19,Thread-0,5,main].start()23 writerThread[#20,Thread-1,5,main].start()24 reader.join()25 writer.join()def readAction(name: String, suffix: String, number: Int): Unit =
6def readAction(nameread: String, suffixdb: String, number8: Int): Unit = {7 context⟨ThreadLocal A⟩.set(nameread + "-" + suffixdb)8 firstValue = context⟨ThreadLocal A⟩.get() + ":" + number89}writer.start()
22reader.start()23writerThread[#20,Thread-1,5,main].start()24readerThread[#19,Thread-0,5,].join()25writer.join()def writeAction(name: String, suffix: String, number: Int): Unit =
11def writeAction(namewrite: String, suffixdb: String, number9: Int): Unit = {12 context.set(name + "-" + suffix)writer ← Thread[#20,Thread-1,5,]
11 def writeAction(name: String, suffix: String, number: Int): Unit = {12 context⟨ThreadLocal A⟩.set(namewrite + "-" + suffixdb)13 secondValue = context⟨ThreadLocal A⟩.get() + ":" + number914 }1516 def main(args: Array[String]): Unit = {17 val suffix = "db"1819 val reader = Thread(() => readAction("read", suffix, 8))20 val writer = Thread(() => writeAction("write", suffix, 9))2122 reader.start()23 writer.start()24 reader.join()25 writer→ Thread[#20,Thread-1,5,].join()2627 println(firstValueread-db:8)28 println(secondValuewrite-db:9)29 }30}outputread-db:8 write-db:9
suffix ← cache, reader ← Thread[#19,Thread-0,5,main], writer ← Thread[#20,Thread-1,5,main]
16def main(args: Array[String]): Unit = {17 val suffix→ cache = "cache"1819 val reader→ Thread[#19,Thread-0,5,main] = Thread(() => readAction("read", suffix, 8))20 val writer→ Thread[#20,Thread-1,5,main] = Thread(() => writeAction("write", suffix, 9))2122 readerThread[#19,Thread-0,5,main].start()23 writerThread[#20,Thread-1,5,main].start()24 reader.join()25 writer.join()def readAction(name: String, suffix: String, number: Int): Unit =
6def readAction(nameread: String, suffixcache: String, number8: Int): Unit = {7 context⟨ThreadLocal A⟩.set(nameread + "-" + suffixcache)8 firstValue = context.get() + ":" + number9}writer.start()
6def readAction(name: String, suffix: String, number: Int): Unit = {7 context⟨ThreadLocal A⟩.set(nameread + "-" + suffixcache)8 firstValue = context.get() + ":" + number9}1011def writeAction(name: String, suffix: String, number: Int): Unit = {12 context.set(name + "-" + suffix)13 secondValue = context.get() + ":" + number14}1516def main(args: Array[String]): Unit = {17 val suffix = "cache"1819 val reader = Thread(() => readAction("read", suffix, 8))20 val writer = Thread(() => writeAction("write", suffix, 9))2122 reader.start()23 writerThread[#20,Thread-1,5,main].start()24 readerThread[#19,Thread-0,5,main].join()25 writer.join()def writeAction(name: String, suffix: String, number: Int): Unit =
7 context.set(name + "-" + suffix)8 firstValue = context⟨ThreadLocal A⟩.get() + ":" + number89}1011def writeAction(namewrite: String, suffixcache: String, number9: Int): Unit = {12 context⟨ThreadLocal A⟩.set(namewrite + "-" + suffixcache)13 secondValue = context⟨ThreadLocal A⟩.get() + ":" + number914}reader ← Thread[#19,Thread-0,5,]
23 writer.start()24 reader→ Thread[#19,Thread-0,5,].join()25 writerThread[#20,Thread-1,5,].join()2627 println(firstValueread-cache:8)28 println(secondValuewrite-cache:9)29 }30}outputread-cache:8 write-cache:9