DevilKing's blog

冷灯看剑,剑上几分功名?炉香无需计苍生,纵一穿烟逝,万丈云埋,孤阳还照古陵

0%

Achieving concurrency in Go

原文链接

thread goroutine
Os threads are managed by kernal and has hardware dependencies. goroutines are managed by go runtime and has no hardware dependencies.
Os threads generally have fixed stack size of 1-2MB goroutines typically have 8KB (2KB since Go 1.4) of stack size in newer versions of go
Stack size is determined during compile time and can not grow Stack size of go is managed in run-time and can grow up to 1GB which is possible by allocating and freeing heap storage
There is no easy communication medium between threads. There is huge latency between inter-thread communication. goroutine use channels to communicate with other goroutines with low latency (read more).
Threads have identity. There is TID which identifies each thread in a process. goroutine do not have any identity. go implemented this because go does not have TLS(Thread Local Storage).
Threads have significant setup and teardown cost as a thread has to request lots of resources from Os and return once it’s done. goroutines are created and destoryed by the go’s runtime. These operations are very cheap compared to threads as go runtime already maintain pool of threads for goroutines. In this case Os is not aware of goroutines.
Threads are preemptively scheduled (read here). Switching cost between threads is high as scheduler needs to save/restore more than 50 registers and states. This can be quite significant when there is rapid switching between threads. goroutines are coopertively scheduled (read more). When a goroutine switch occurs, only 3 registers need to be saved or restored.

原文链接2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package main

import (
"fmt"
"time"
)

var start time.Time

func init() {
start = time.Now()
}

func getChars(s string) {
for _, c := range s {
fmt.Printf("%c at time %v\n", c, time.Since(start))
time.Sleep(10 * time.Millisecond)
}
}

func getDigits(s []int) {
for _, d := range s {
fmt.Printf("%d at time %v\n", d, time.Since(start))
time.Sleep(30 * time.Millisecond)
}
}

func main() {
fmt.Println("main execution started at time", time.Since(start))

// getChars goroutine
go getChars("Hello")

// getDigits goroutine
go getDigits([]int{1, 2, 3, 4, 5})

// schedule another goroutine
time.Sleep(200 * time.Millisecond)

fmt.Println("\nmain execution stopped at time", time.Since(start))
}