4. Go进阶
4.1 Goroutine
线程与协程
协程:用户态轻量级线程,kb级别 线程:内核态线程跑多个协程,mb级别
func hello(i int) {
println("hello goroutine:" + fmt.Sprint(i))
}
func main() {
for i := 0; i < 5; i++ {
go func(j int) {
hello(j)
}(i)
}
time.Sleep(time.Second)
}
hello goroutine:1 hello goroutine:2 hello goroutine:3 hello goroutine:0 hello goroutine:4
4.2 CSP
go提倡通过通信共享内存而不是通过共享内存进行通信
4.3 Channel
make(chan 元素类型,[缓冲大小])
- 无缓冲通道 make(chan int)
- 有缓冲通道 make(chan int, 2)
- 子协程发送0~9数字
- 子协程计算输入数字的平方
- 主协程输出最后平方数
package main
func main() {
src := make(chan int)
dest := make(chan int, 3)
go func() {
// 生产
defer close(src)
for i := 0; i < 10; i++ {
src <- i
}
}()
go func() {
// 消费
defer close(dest)
for i := range src {
dest <- i * i
}
}()
for i := range dest {
// 复杂操作
println(i)
}
}
4.4 并发安全Lock
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 main() {
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)
}
4.5 WaitGroup
计数器
开启协程+1;执行结束-1;主协程阻塞到计数器为0
快速打印hello goroutine:0~4
旧[不安全]
func hello(i int) {
println("hello goroutine: " + fmt.Sprint(i))
}
func main() {
for i := 0; i < 5; i++ {
go func(j int) {
hello(j)
}(i)
}
time.Sleep(time.Second)
}
新[安全]
func hello(i int) {
println("hello goroutine: " + fmt.Sprint(i))
}
func main() {
var wg sync.WaitGroup
// 计数器+delta
wg.Add(5)
for i := 0; i < 5; i++ {
go func(j int) {
// 计数器-1
defer wg.Done()
hello(j)
}(i)
}
// 主协程阻塞 计数器为0->推出主协程
wg.Wait()
}