GMP 模型

第一个版本只有gm模型,有一个全局的锁来维护gm模型,导致性能比较低
第二个版本引入了p,p绑定了一个本地g队列,同时还有一个全局g队列,p会先从本地获取g,如果本地没有g的话,会根据一个算法从全局g队列拿一批g,全局也没有的话,会从其他p上的g队列拿取一半,这样本地队列是没有锁的竞争,也减小就m的压力,但是这个还是会存在一个g长期占用m导致其他g饿死
第三个版本增加了抢占式调度.系统会启用一个sysmon的线程来监听全局的g的调度信息,如果一个g长期占用好像是10ms,就会让g停止,放到队列后,运行下一个g,这样也会出现如果一个g只进行计算,没进行函数调用的话,还是会一直占用

G 什么时候会出现堵塞

io操作、锁操作

GC 怎么触发

两种方式1.主动调用:使用代码调用gc的方法
1.被动的话有两个触发方式:1.当内存分配到达一个阈值,就会触发gc.然后这个阈值又会增加一倍,第二种就是每隔2min就会触发一次gc.

Mutex

Mutex 是最简单的一种锁类型,同时也比较暴力,当一个 goroutine 获得了 Mutex 后,其他 goroutine 就只能乖乖等到这个 goroutine 释放该 Mutex。互斥锁占用8字节
正常模式,先进先出的队列形式获取锁,饥饿模式是当一个goroutine获取锁的时候,此时的goroutine超过1s没有获取到锁.其他的gorpoutine获取了,这就是饥饿模式,优化是,知乎交给队列的最先goroutine
饥饿模式的解除,是当goroutine是队列的最后一个,或者1s之内获取了锁,就回回到正常模式
当加锁的时候,状态不是0,就会在正常模式下进入自旋模式,多CPU自旋次数小于4次运行队列P绑定M,解锁的时候只需要修改相应的状态就可以

读写锁

读写锁我们一般用于全部变量上

sync.map

他是使用了两个结构read和dict,通过空间换时间,减少锁的竞争,存数据时,判断key存在read里没,如果存在就更新值,如果不存在就将read里未标记删除的数据同步到dirty下,而删除的时候只是将read的值置为nil,只有read提升dirty时就会清理删掉的数据


汝何不上九霄
4.7k 声望1.6k 粉丝