Concurrency Basics
Worker Sequence
A single worker goroutine processes queued jobs in send order.
worker
A worker reads jobs from a channel and writes results to another channel.
Worker Sequence
worker_sequence.go
Replay: real traced execution (multi-file project)
package main
import "fmt"
func main() {
var extraJob = 3
jobs := make(chan int, 3)
results := make(chan int, 3)
go func() {
for job := range jobs {
results <- job * 10
}
}()
inputs := []int{1, 2, extraJob}
for _, job := range inputs {
jobs <- job
}
close(jobs)
first := <-results
second := <-results
third := <-results
fmt.Println("jobs=", len(inputs))
fmt.Println("first=", first)
fmt.Println("second=", second)
fmt.Println("third=", third)
}
package main
import "fmt"
func main() {
var extraJob = 4
jobs := make(chan int, 3)
results := make(chan int, 3)
go func() {
for job := range jobs {
results <- job * 10
}
}()
inputs := []int{1, 2, extraJob}
for _, job := range inputs {
jobs <- job
}
close(jobs)
first := <-results
second := <-results
third := <-results
fmt.Println("jobs=", len(inputs))
fmt.Println("first=", first)
fmt.Println("second=", second)
fmt.Println("third=", third)
}
package main
import "fmt"
func main() {
var extraJob = 5
jobs := make(chan int, 3)
results := make(chan int, 3)
go func() {
for job := range jobs {
results <- job * 10
}
}()
inputs := []int{1, 2, extraJob}
for _, job := range inputs {
jobs <- job
}
close(jobs)
first := <-results
second := <-results
third := <-results
fmt.Println("jobs=", len(inputs))
fmt.Println("first=", first)
fmt.Println("second=", second)
fmt.Println("third=", third)
}
extraJob ← 3, jobs ← (chan int)(⟨addr A⟩), results ← (chan int)(⟨addr B⟩)
5func main() {6 var extraJob→ 3 = 3 //@extraJob=4, 57 jobs→ (chan int)(⟨addr A⟩) := make(chan int, 3)8 results→ (chan int)(⟨addr B⟩) := make(chan int, 3)910 go func() {11 for job := range jobs {12 results <- job * 1013 }14 }()1516 inputs→ []int{1, 2, 3} := []int{1, 2, extraJob3}17 for _, job := range inputs {for _, job := range inputs
pass 1 of 316inputs := []int{1, 2, extraJob}17for _, job1 := range inputs[]int{1, 2, 3} {18 jobs(chan int)(⟨addr A⟩) <- job119}All 3 passes — pass 1 is the card above pass job1 1 2 2 3 3 close(jobs)
19}20close(jobs(chan int)(⟨addr A⟩))2122first := <-results(chan int)(⟨addr B⟩)23second := <-resultsfor job := range jobs
pass 1 of 310go func() {11 for job1 := range jobs(chan int)(⟨addr A⟩) {12 results(chan int)(⟨addr B⟩) <- job1 * 1013 }All 3 passes — pass 1 is the card above pass job1 1 2 2 3 3 first ← 10, second ← 20, third ← 30
22 first→ 10 := <-results(chan int)(⟨addr B⟩)23 second→ 20 := <-results(chan int)(⟨addr B⟩)24 third→ 30 := <-results(chan int)(⟨addr B⟩)25 fmt.Println("jobs=", len(inputs[]int{1, 2, 3}))26 fmt.Println("first=", first10)27 fmt.Println("second=", second20)28 fmt.Println("third=", third30)29}outputjobs= 3 first= 10 second= 20 third= 30
extraJob ← 4, jobs ← (chan int)(⟨addr A⟩), results ← (chan int)(⟨addr B⟩)
5func main() {6 var extraJob→ 4 = 47 jobs→ (chan int)(⟨addr A⟩) := make(chan int, 3)8 results→ (chan int)(⟨addr B⟩) := make(chan int, 3)910 go func() {11 for job := range jobs {12 results <- job * 1013 }14 }()1516 inputs→ []int{1, 2, 4} := []int{1, 2, extraJob4}17 for _, job := range inputs {for _, job := range inputs
pass 1 of 316inputs := []int{1, 2, extraJob}17for _, job1 := range inputs[]int{1, 2, 4} {18 jobs(chan int)(⟨addr A⟩) <- job119}All 3 passes — pass 1 is the card above pass job1 1 2 2 3 4 close(jobs)
19}20close(jobs(chan int)(⟨addr A⟩))2122first := <-results(chan int)(⟨addr B⟩)23second := <-resultsfor job := range jobs
pass 1 of 310go func() {11 for job1 := range jobs(chan int)(⟨addr A⟩) {12 results(chan int)(⟨addr B⟩) <- job1 * 1013 }All 3 passes — pass 1 is the card above pass job1 1 2 2 3 4 first ← 10, second ← 20, third ← 40
22 first→ 10 := <-results(chan int)(⟨addr B⟩)23 second→ 20 := <-results(chan int)(⟨addr B⟩)24 third→ 40 := <-results(chan int)(⟨addr B⟩)25 fmt.Println("jobs=", len(inputs[]int{1, 2, 4}))26 fmt.Println("first=", first10)27 fmt.Println("second=", second20)28 fmt.Println("third=", third40)29}outputjobs= 3 first= 10 second= 20 third= 40
extraJob ← 5, jobs ← (chan int)(⟨addr A⟩), results ← (chan int)(⟨addr B⟩)
5func main() {6 var extraJob→ 5 = 57 jobs→ (chan int)(⟨addr A⟩) := make(chan int, 3)8 results→ (chan int)(⟨addr B⟩) := make(chan int, 3)910 go func() {11 for job := range jobs {12 results <- job * 1013 }14 }()1516 inputs→ []int{1, 2, 5} := []int{1, 2, extraJob5}17 for _, job := range inputs {for _, job := range inputs
pass 1 of 316inputs := []int{1, 2, extraJob}17for _, job1 := range inputs[]int{1, 2, 5} {18 jobs <- jobAll 3 passes — pass 1 is the card above pass jobjobs1 1 — 2 2 — 3 5 (chan int)(⟨addr A⟩) jobs <- job
17for _, job := range inputs {18 jobs(chan int)(⟨addr A⟩) <- job119}for job := range jobs
pass 1 of 310go func() {11 for job1 := range jobs(chan int)(⟨addr A⟩) {12 results <- job * 10All 3 passes — pass 1 is the card above pass jobresults1 1 — 2 2 (chan int)(⟨addr B⟩) 3 5 (chan int)(⟨addr B⟩) jobs <- job
11 for job := range jobs {12 results(chan int)(⟨addr B⟩) <- job1 * 1013 }14}()1516inputs := []int{1, 2, extraJob}17for _, job := range inputs {18 jobs(chan int)(⟨addr A⟩) <- job219}jobs <- job
17for _, job := range inputs {18 jobs(chan int)(⟨addr A⟩) <- job219}first ← 10, second ← 20
19}20close(jobs(chan int)(⟨addr A⟩))2122first→ 10 := <-results(chan int)(⟨addr B⟩)23second→ 20 := <-results(chan int)(⟨addr B⟩)24third := <-results(chan int)(⟨addr B⟩)25fmt.Println("jobs=", len(inputs))third ← 50
23 second := <-results24 third→ 50 := <-results(chan int)(⟨addr B⟩)25 fmt.Println("jobs=", len(inputs[]int{1, 2, 5}))26 fmt.Println("first=", first10)27 fmt.Println("second=", second20)28 fmt.Println("third=", third50)29}outputjobs= 3 first= 10 second= 20 third= 50