《go并发编程实战》笔记

cpu用户态 内核态切换
用户空间 内核空间
系统调用:原子操作,不可中断
互斥:保持只有一个线程对资源访问(进入临界区)

管道:匿名 命名
单向,阻塞(未就绪,缓冲区满),不提供操作原子性(写)
内存管道:可并发访问

信号:软件模拟硬件中断
进程处理信号:记录并处理一次(不保证顺序)

线程
线程模型:n-1、1-1(linux)、n:m
线程同步:
互斥量:阻塞等待锁。互斥量使用前初始化,且初始化保证唯一性
解决死锁:试锁回退,顺序加锁
条件变量:(绑定互斥量)通知单发||多发

go并发机制
Machine:内核调度单位
Processor:
Goroutine:代码执行单位
M与P关联(1对1),执行G(1对多)

M:
创建:执行P。创建内核线程——初始化栈空间、信号处理——执行next p || (后台应用:GC、监控)执行起始函数
自旋(寻找G):执行机会
锁定:M-G关联
分离:G阻塞时
停止:gc,M放入空闲M-list
限制:资源(地址空间、PID、内存?)

P:G队列
runnext:G
可运行G-list:待运行G
自由G-list:已运行G
状态:
idle || running P-M无关联||关联
syscall:G syscall
gcstop:停止调度
dead

G:
状态:
idle
runnable
running
syscall:G-P分离
waiting:G-P分离
dead:放入自由G-list
copystack
scan(用于组合)

调度器行为:(M中)
前置检查:
存在M-G锁定(cgo || 线程本地存储):检查M,暂时阻塞M,停止调度。发现G可运行,且锁定M,唤醒M
检测到待运行串行任务(STW),停止并阻塞M,执行完成则唤醒

调度主体:寻找G(runnable)
触发:用户程序初始化,全局mainG
G运行结束、阻塞、退出syscall、栈增长、调用标准库函数(runtime.Goshed || Goexit)

查找G:
阶段1
终结器 G:终结器与对相关联,对象不可达时触发
G-list(runnable)(P、调度器)
netpoller(非阻塞),取已经接收到通知的G
P-list (非空闲P)(M在自旋 or 自旋M < 非空P/2)随机取

阶段2
GC标记 G:
G-list:调度器
P-list遍历取
取空闲P,执行GC G
netpoller(非阻塞)

无G:停止M

M-P关联,解除触发:
M-G关联

posted @ 2020-12-08 20:19  qmchao  阅读(189)  评论(0)    收藏  举报