一、语言进阶(并发编程)
并发:如图左,多个线程程序在一个核的CPU上执行
并行:如图右,多个线程程序在多个核的CPU上执行
1. Goroutine
协程:用户态,轻量级线程,栈KB级别。
线程:内核态,线程跑多个协程,栈MB级别。
例子:打印hello goroutine
package main
import (
"fmt"
"time"
)
func hello(i int) {
println("hello goroutine : " + fmt.Sprint(i))
}
func HelloGoRoutine() {
for i := 0; i < 5; i++ {
go func(j int) {
hello(j)
}(i)
}
time.Sleep(time.Second)
}
func main() {
HelloGoRoutine()
}
运行结果:
2. CSP (Communicating Sequential Processes)
3. Channel
例子(通过通讯来共享内存):
package main
func CalSquare() {
src := make(chan int)
dest := make(chan int, 3)
// 运行A协程
go func() {
defer close(src)
for i := 0; i < 10; i++ {
src <- i
}
}()
// 运行B协程
go func() {
defer close(dest)
for i := range src {
dest <- i * i
}
}()
// 主线程
for i := range dest {
println(i)
}
}
func main() {
CalSquare()
}
4. 并发安全(Lock)
例子:通过共享内存通信
package main
import (
"sync"
"time"
)
var (
x int64
lock sync.Mutex
)
func addWithLock() {
for i := 0; i < 2000; i++ {
lock.Lock()
x += 1
lock.Unlock()
}
}
func addWithoutLock() {
for i := 0; i < 2000; i++ {
x += 1
}
}
func Add() {
x = 0
for i := 0; i < 5; i++ {
go addWithoutLock()
}
time.Sleep(time.Second)
println("WithoutLock:", x)
x = 0
for i := 0; i < 5; i++ {
go addWithLock()
}
time.Sleep(time.Second)
println("WithLock:", x)
}
func main() {
Add()
}
运行结果,通过多次运行,不加锁的情况可能会导致结果不符合预期:
1.5 WaitGroup
例子:
package main
import (
"fmt"
"sync"
)
func hello(i int) {
println("hello goroutine : " + fmt.Sprint(i))
}
func ManyGoWait() {
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
go func(j int) {
defer wg.Done()
hello(j)
}(i)
}
wg.Wait()
}
func main() {
ManyGoWait()
}