Goroutine
Goroutine is like the thread in Go, which makes Go create multitask.
Only calls goroutine in main function when program started, which names main goroutine.
go a(x, y)
Function begin with go can make a
run in another goroutine.
Main goroutine end, other goroutine will be force to close.
Single Thread
Each lines of program is executed by sequence
1 | func main() { |
Output:
1 | Ni |
Multiple Thread
Execute goroutine which is the number of CPU in the same time at most.
1 | func main() { |
Output:
1 | How |
Wait
Here comes the problem which needs waiting.
When main
goroutine closed, others two goroutine will be force to close and lead to error.
Sol: Wait other goroutine end and close main goroutine.
1 | func main(){ |
It contains 3 goroutine:
main
go reply("Ni")
go reply("How")
Three ways to wait
time.Sleep
: sleep in specific timesync.WaitGroup
: Wait until specific numbers ofDone()
use- Channel block: use wait when received this characteristic to avoid thread keep executing
time.Sleep
1 | func main() { |
cons: It doesn’t know the goroutine execution time is greater or less than sleep time.
sync.WaitGroup
1 | func main() { |
Create WaitGroup
Counter which numbers is same as the goroutine that want to wait.
Put WaitGroup
to goroutine, using wg.Done()
to minus 1 when execution finished.
wg.Wait()
will wait until counter to 0.
Channel
1 | func main() { |
1 | How |
With 2 goroutine, need to wait 2 End
push into channel to end main goroutine.
Race Condition
Multi-Thread Shared Variables
1 | func main() { |
Ex: Current in 60, while in multi-thread
goroutine1
get 60 to addgoroutine2
probably gottotal
value beforegoroutine1
dototal++
- In this condition, the result will be 61, not 62
Doing the addition in the same total
variable in multiple goroutine will lead to operation error because it cannot make sure the secure of value when assign it. => Race Condition
There are 2 solutions:
- Sync.Mutex
- Channel
Sync.Mutex (互斥鎖)
1 | type SafeNumber struct { |
1 | 1000 |
Via Channel - security of variable
1 | func main() { |
1 | 1000 |
- When
goroutine1
pull out, and there is nothing in Channel - Because there is nothing in Channel, cause
goroutine2
waiting - When
goroutine1
finished,total
pushed to Channel - When
goroutine2
find out there is something in Channel, pull out and wait to operate.