0% found this document useful (0 votes)
115 views14 pages

Concurrecy in Golang

Goroutines are lightweight threads managed by the Go runtime. The scheduler maps multiple goroutines to OS threads using an M:N model. Goroutines use a fork-join model where new goroutines are created using 'go' and synchronization is achieved through join points like waitgroups. Memory usage of a goroutine is around 2-3 KB. Concurrency constructs like mutex, RWMutex, and condition variables from the sync package provide synchronization between goroutines.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
115 views14 pages

Concurrecy in Golang

Goroutines are lightweight threads managed by the Go runtime. The scheduler maps multiple goroutines to OS threads using an M:N model. Goroutines use a fork-join model where new goroutines are created using 'go' and synchronization is achieved through join points like waitgroups. Memory usage of a goroutine is around 2-3 KB. Concurrency constructs like mutex, RWMutex, and condition variables from the sync package provide synchronization between goroutines.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd

CONCURRENCY

IN GO

1
GOROUTINES FUNDAMENTAL UNIT

01 02 03
Function running Not OS threads or Concurrent coroutines
concurrently green threads which are not pre-
alongside other code (threads managed by emptive i.e. they can’t
a language’s runtime) be interrupted

2
M:N scheduler

M Mapped To N
Green OS
Threads Threads

3
FORK JOIN MODEL

sayHello := func() {
fmt.Println(“Hello from Goroutine”);
}

/* No Join point */
go sayHello()

4
ISSUES IN PREVIOUS CODE

**NO JOIN POINT


Fixes available :
 time.Sleep(1 * time.Millisecond)) It
creates a race condition
 Introduce a Join point It
guarantees program’s correctness and remove the
race condition
CREATING A JOIN POINT
var wg sync.WaitGroup
sayHello := func() {
defer wg.Done()
fmt.Println(“Hello from Goroutine”);
}
wg.Add(1)
go sayHello()
wg.Wait() This is the Join point
6
MEMORY USAGE BY A GOROUTINE

 ~ 2-3 Kb memory allocated to goroutine when


created
 Go runtime grows or shrinks memory for
storage automatically
 Goroutines share same address space
 GC does NOTHING to collect abandoned
goroutines. Blocked goroutines hang around
until process exits.
7
MEMORY USAGE BY GOROUTINE
package main

import (
"fmt"
"runtime"
"sync"
)

/* Program to understand memory allocated to newly created goroutines */


func main() {
memConsumed := func() uint64 {
runtime.GC()
var s runtime.MemStats
runtime.ReadMemStats(&s)
return s.Sys
}
8
MEMORY USAGE BY GOROUTINE
var c <-chan interface{}
var wg sync.WaitGroup
noop := func() {
wg.Done()
// Blocking read operation on empty channel keeping the goroutine alive
<-c
}
const numGoroutines = 1e4
wg.Add(numGoroutines)
before := memConsumed()
for i := numGoroutines; i > 0; i-- {
// Kicking in new goroutine
go noop()
}
wg.Wait()
after := memConsumed()
fmt.Printf("%.3fkb", float64(after-before)/numGoroutines/1000)
9
}
waitGroup from sync package
hello := func(wg *sync.WaitGroup, id int) {
defer wg.Done()
fmt.Printf("Hello from %v!\n", id)
}
const numGreeters = 3
var wg sync.WaitGroup
wg.Add(numGreeters)
go hello(&wg, 1)
go hello(&wg, 2)
go hello(&wg, 3)

wg.Wait()

10
Mutex & RWMutex from sync package
CONCURRENCY CONSTRUCT FOR SHARING ACCESS VIA SYNCHRONISATION

Goroutine 1 Goroutine 2

Lock()

MUTEX
Lock acquired
Lock()
Failed to acquire Lock

Unlock()
Lock released

MUTEX
Lock()
Lock acquired
11
Mutex & RWMutex from sync package
var count int for i := 0; i <= 5; i-- { // Increment
var lock sync.Mutex arithmetic.Add(1)
increment := func(){ go func() {
lock.Lock() defer arithmetic.Done()
defer lock.Unlock() increment()
count++ }()
fmt.Printf(”+ing: %d\n", count) }
} for i := 0; i <= 5; i-- { // Decrement
decrement := func() { arithmetic.Add(1)
lock.Lock() go func() {
defer lock.Unlock() defer arithmetic.Done()
count–- decrement()
fmt.Printf(”-ing: %d\n", count) }()
} }
var arithmetic sync.WaitGroup arithmetic.Wait()
fmt.Println("Arithmetic complete.") 12
Mutex & RWMutex from sync package
Goroutine 1 Goroutine 2

RLock()

RWMUTEX
Lock acquired
RLock()

Lock() Lock acquired


Failed to acquire lock
RUnlock()
RUnlock() Read Lock released

RWMUTEX
Read Lock released

Lock()
Full Lock acquired 13
c := sync.NewCond(&sync.Mutex{})
Cond queue := make([]interface{}, 0, 10)
removeFromQueue := func(delay time.Duration) {
time.Sleep(delay)
c.L.Lock()
queue = queue[1:]
fmt.Println("Removed from queue")
c.L.Unlock()
for conditionTrue() == false { c.Signal()
}
}
A condition waiting to be met for i := 0; i < 10; i++ {
to break the loop and let c.L.Lock()
goroutine continue execution for len(queue) == 2 {
c.Wait()
}
fmt.Println("Adding to queue")
queue = append(queue, struct{}{})
go removeFromQueue(1 * time.Second)
c.L.Unlock() 14

You might also like