扩容时map并不会立即把新数据做迁移,而是当访问原来旧bucket的数据的时候,才把旧数据做迁移,如下图:
注意:这里并不会直接删除旧的bucket,而是把原来的引用去掉,利用GC清除内存 。
map中数据的删除
如果理解了map的整体结构 , 那么查找、更新、删除的基本步骤应该都很清楚了 。这里不再赘述 。
值得注意的是,找到了map中的数据之后,针对key和value分别做如下操作:
1
2
3
4
1、如果``key``是一个指针类型的 , 则直接将其置为空 , 等待GC清除;
2、如果是值类型的,则清除相关内存 。
3、同理,对``value``做相同的操作 。
4、最后把key对应的高位值对应的数组index置为空 。
【golang详解】go语言GMP(GPM)原理和调度Goroutine调度是一个很复杂的机制,下面尝试用简单的语言描述一下Goroutine调度机制 , 想要对其有更深入的了解可以去研读一下源码 。
首先介绍一下GMP什么意思:
G ----------- goroutine: 即Go协程,每个go关键字都会创建一个协程 。
M ---------- thread内核级线程,所有的G都要放在M上才能运行 。
P ----------- processor处理器 , 调度G到M上 , 其维护了一个队列,存储了所有需要它来调度的G 。
Goroutine 调度器P和 OS 调度器是通过 M 结合起来的,每个 M 都代表了 1 个内核线程 , OS 调度器负责把内核线程分配到 CPU 的核上执行
模型图:
避免频繁的创建、销毁线程,而是对线程的复用 。
1)work stealing机制
当本线程无可运行的G时,尝试从其他线程绑定的P偷取G,而不是销毁线程 。
2)hand off机制
当本线程M0因为G0进行系统调用阻塞时 , 线程释放绑定的P , 把P转移给其他空闲的线程执行 。进而某个空闲的M1获取P , 继续执行P队列中剩下的G 。而M0由于陷入系统调用而进被阻塞,M1接替M0的工作,只要P不空闲,就可以保证充分利用CPU 。M1的来源有可能是M的缓存池,也可能是新建的 。当G0系统调用结束后,根据M0是否能获取到P,将会将G0做不同的处理:
如果有空闲的P,则获取一个P , 继续执行G0 。
如果没有空闲的P,则将G0放入全局队列,等待被其他的P调度 。然后M0将进入缓存池睡眠 。
如下图
GOMAXPROCS设置P的数量 , 最多有GOMAXPROCS个线程分布在多个CPU上同时运行
在Go中一个goroutine最多占用CPU 10ms , 防止其他goroutine被饿死 。
具体可以去看另一篇文章
【Golang详解】go语言调度机制 抢占式调度
当创建一个新的G之后优先加入本地队列,如果本地队列满了,会将本地队列的G移动到全局队列里面 , 当M执行work stealing从其他P偷不到G时,它可以从全局G队列获取G 。
协程经历过程
我们创建一个协程 go func()经历过程如下图:
说明:
这里有两个存储G的队列,一个是局部调度器P的本地队列、一个是全局G队列 。新创建的G会先保存在P的本地队列中 , 如果P的本地队列已经满了就会保存在全局的队列中;处理器本地队列是一个使用数组构成的环形链表,它最多可以存储 256 个待执行任务 。
G只能运行在M中,一个M必须持有一个P , M与P是1:1的关系 。M会从P的本地队列弹出一个可执行状态的G来执行,如果P的本地队列为空,就会想其他的MP组合偷取一个可执行的G来执行;
一个M调度G执行的过程是一个循环机制;会一直从本地队列或全局队列中获取G
推荐阅读
- 如何做好机械设备营销,如何做好机械设备营销管理
- 雨课堂下载,长江雨课堂下载
- 棋牌游戏记牌的简单介绍
- vb.netdism的简单介绍
- 安卓仿ios联动选择器,安卓仿ios联动选择器下载
- vb.net打印预览 vb窗口打印
- erp管理系统企业用得着吗,erp管理系统好处
- 电商如何切入社群,社群电商商业模式
- 两仪Android虚拟机,安卓虚拟机搭建