20230120日志
2023年1月20日
golang #
基本概念 #
不能直接创建Thread, 但是可以创建goroutine; os线程由os调度, goroutine在os线程内由goruntime调度; GOMAXPROCS定义产生多少OS线程, 在有block时, 还会生成新的OS线程, GOMAXPROCS默认等于机器的逻辑核心数; goroutine的状态, Executing: 在OS线程上运行, Runnable: 等待进入Executing, Waitting: stopped并等待一些事情完成(system call, sync, wait mutex); 1.14之前只会在chan send/recieve, i/o, wait mutext时发生context switch, 之后的版本会将运行超过10ms的goroutine标记为preemptible, 并有机会context-switched off被其他goroutine替换
使用mutex还是channel #
通常并行使用mutext, 并发使用channel
Data race 和 Race conditions #
- Data race: 不同的goroutine,同时访问相同的内存, 至少一个goroutine在write
- Race conditions: 不是Data race的场景也可能是Race conditions; 不确定哪个goroutine先运行; 不确认channel发送数据多快; 不确定读取数据库的耗时
内存模型 #
内存模式是为了保证避免 Data race
- 无Data race
i := 0
go func() {
i++
}()
- 有Data race
i := 0
go func() {
i++
}()
fmt.Println(i)
- 无Data race
i := 0
ch := make(chan struct{})
go func() {
<-ch
fmt.Println(i)
}()
i++
ch <- struct{}{}
variable increment < channel send < channel receive < variable read
- 无Data race
i := 0
ch := make(chan struct{})
go func() {
<-ch
fmt.Println(i)
}()
i++
close(ch)
variable increment < close < channel receive < variable read
- 有Data race(有缓冲)
i := 0
ch := make(chan struct{}, 1) // 有缓冲
go func() {
i = 1
<-ch
}()
ch <- struct{}{}
fmt.Println(i)
- 无Data race(无缓冲)
i := 0
ch := make(chan struct{})
go func() {
i = 1
<-ch
}()
ch <- struct{}{}
fmt.Println(i)
启动多少线程 #
- cpu bound类型的使用和GOMAXPROCS一致的数据,不到GOMAXPROCS时和任务数量一致
- i/o bound类型需要根据外部系统判断
Context的理解 #
- 1个接口(Context)
- 4个具体实现(emptyCtx, cancelCtx, timerCtx, valueCtx)
- 6个方法(Background, TODO, WithCancel, WithDeadline, WithTimeout, WithValue)