ConcurrencyinGo
JaapGroeneveld-jGroeneveld.de
ConcurrencyvsParallelism
ConcurrencyProgramming:Compositionofindependentlyexecutingprocesses
ParallelProgramming:Simultaneousexecutionof(possiblyrelated)
computations.
.
Concurrencyisaboutdealingwithlotsofthingsatonce.
Parallelismisaboutdoinglotsofthingsatonce.
Notthesame,butrelated.
Concurrencyisaboutstructure,parallelismisaboutexecution.
Concurrencyprovidesawaytostructureasolutiontosolveaproblemthatmay(but
notnecessarily)beparallelizable.
.RobPike:ConcurrencyvsParallelism 2
Goprovidesconcurrency
Concurrentexecution(goroutines)
Synchronizationandmessaging(channels)
Multi-wayconcurrentcontrol(select)
3
Goroutines
Agoroutineisafunctionrunningindependentlyinthesameaddressspaceasother
goroutines
foo("hello", "world") // foo runs; we wait
go foo("hello", "world") // foo starts running
bar() // does not wait for foo to return
Goroutinesarenotthreads.It'sfinetostartthousandsofgoroutinesatthesametime.Not
allwillruninparallelbutthisallowsforaconcurrentprogrammingmodel.
4
5
Channels
Channelsaretypedvaluesthatallowgoroutinestosynchronizeandexchangeinformation.
ch := make(chan string) // Make Channel for strings
close(ch) // Close Channel
result := <- ch // Read (Blocking until result comes in)
ch <- "hello" // Write (Blocking until read in case of buffer full or no buffer at all)
Theycanbetypedtoonlybeusedforreading <-chan orwriting ->chan
6
Channelsexample
timerChan := make(chan time.Time)
go func() {
time.Sleep(deltaT) // wait for a while
timerChan <- time.Now() // send time on timerChan
}()
// [...] Do something else concurrently
// Receive will block until timerChan delivers.
completedAt := <-timerChan
7
PingPong
8
func pingpong() {
var Ball int
table := make(chan int)
go player("1", table)
go player("2", table)
table <- Ball
time.Sleep(1 * time.Second)
<-table
}
func player(playerName string, table chan int) {
for {
ball := <-table
ball++
time.Sleep(100 * time.Millisecond)
table <- ball
}
}
9
Select
Theselectstatementislikeaswitch,butthedecisionisbasedonabilitytocommunicate
ratherthanequalvalues.
Readfromoneofthechannelsifoneisreadyandthencontinue
select {
case v := <-ch1:
fmt.Println("channel 1 sends", v)
case v := <-ch2:
fmt.Println("channel 2 sends", v)
default: // optional
fmt.Println("neither channel was ready")
}
Ifyouomitthedefaultcasethenthiswaitsuntilsomechannelssendsdata.
10
Mutex
Protectsdataagainstconcurrentaccess.
type Counter struct {
mu sync.Mutex
value int
}
func (c *Counter) Inc() {
c.mu.Lock()
defer c.mu.Unlock()
c.value++
}
ThereisalsoanRWMutextodifferentiatebetweenreadandwritelocking
11
Waitgroup
Useawaitgrouptowaitforanumberofchannelsortaskstofinish
var wg sync.WaitGroup
wg.Add(numberOfTasks)
for i:= 0; i < numberOfTasks; i++ {
go func(w *sync.WaitGroup) {
counter.Inc()
w.Done()
}(&wg)
}
wg.Wait() // block here until all are done
12
Guidelines
Usechannelswhenpassingownershipofdata
Usemutexesformanagingstate
13
Code
Allexampleareincludedinthe src/basic folderwithadditionallogstatementsto
understandthembetter.
14
Errors
Toreceiveerrorsfromgoroutinesitsagreatwayto
useerrorchannels make(chan err)
ortointroduceastructthateitherincludesyourresultoranerror make(chan
struct{Error error, Result MyResultType}) .
Therearealsoconveniencelibrariesforthis.Forexample errgroup .
See src/errors forexamples.
15
Patterns
Fan-In (n producers -> 1 consumer)
Fan-Out (1 producer -> n consumers)
BackgroundWorker
see src/patterns
16
https://yourbasic.org/golang/efficient-parallel-computation/
Morepatterns
17

Jaap Groeneveld - Concurrency in Go