这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天
day2
- 语言进阶(从并发编程视角,了解go适合高并发场景的本质)
- 依赖管理
- 单元测试,上线的最后一环
- 项目实战
-
并发编程
3.1 协程
并发、并行
协程:用户态,轻量级线程,栈MB级别。
线程:内核态,线程跑多个协程,栈KB级别。
内存中heap和stack的区别?
开启协程
在函数的前面加go关键字
协程之间的通信,怎么做到?通过通信来共享内存
3.2 通信共享内存
CSP (Communicating Sequential Processes)
Goroutine: go程序并发的执行体
通道:连接协程,类似传输队列
3.3 通道的具体操作
func CalSquare() {
src := make(chan int)//创建一个channel,生产者
dest := make(chan int, 3) //创建一个channel,消费者
go func() {
defer close(src)
for i := 0; i < 10; i++ {
src <- i
}
close(src)
}()
go func() {
defer close(dest)
for i := range src {
dest <- i * i
}
}()
for i := range dest {
//复杂操作
println(i)
}
}
3.4 并发安全问题:比较难定位。避免对共享内存做些非并发安全的读写操作
代码:加锁和不加锁
package main
import (
"sync"
"time"
)
var (
x int64
lock sync.Mutex //互斥锁
)
// 加锁
func addWithLock() {
for i := 0; i < 2000; i++ {
lock.Lock()
x = x + 1
lock.Unlock()
}
}
// 不加锁
func addWithoutLock() {
for i := 0; i < 2000; i++ {
x = x + 1
}
}
func Add() {
x = 0
for i := 0; i < 5; i++ {
go addWithoutLock()
}
time.Sleep(time.Second) //等待一秒钟
println("WithoutLock:", x)
x = 0
time.Sleep(time.Second) //等待一秒钟
println("WithLock:", x)
}
func main() {
Add()
}
3.5 WaitGroup
小结
go并发编程有3种
这里简单做个小结,整个章节主要涉及3个方面,一个是协程,通过高效的调度模型实现高并发操作,一个是通道channel,通过通信实现共享内存,最后sync相关关键字,实现并发安全操作和协程间的同步。
-
依赖管理
4.1 go依赖管理的演进:
4.2 依赖管理三要素 (类似Maven)
1.配置文件,描述依赖:go.mod
2.中心仓库管理依赖库 Proxy
3.本地工具 go get/mod