Golang go关键字原理

goroutine的创建通过go关键字调用newproc函数实现,newproc在系统线程栈上执行逻辑,包括调用newproc1创建新goroutine并将其添加到调度队列。newproc1会尝试从gfree列表获取或创建g,分配栈空间,并初始化gobuf结构体,最后将goroutine状态设为_Grunnable准备运行。

        go关键字运行一个函数会创建一个新的goroutine执行函数。编译器会把go语句转成对runtime.newproc()函数的调用,这个函数使用systemstack()函数切换到g0的栈上:
        1)执行newproc1()函数,newproc1()函数先尝试从P的gFree的gList中获取空闲的g,如果获取不到则从全局的gFree中批量取一部分,返回一个g。如果都没有获取到,则调用malg()新创建一个goroutine,分配内存并初始化相关数据结构,把函数的起始地址赋值给新goroutine的startpc成员。
        2)调用runqput()把新goroutine加入到运行队列,优先放到当前P的本地队列,因为不需要加锁。首先,通过CAS原子操作把新goroutine设置成下一个要执行的g,也就是当前P的runnext成员变量。之前的那个oldnext会被移动到队列的末尾。如果队列已满,则调用runqputslow()移动一半的g到全局队列。访问全局队列的过程需要加锁。
        3)调用wakep()尝试唤醒空闲的P、M执行调度。

newproc1()函数流程:

        1. 首先,如果P本地的gFree的gList不空,尝试从中获取空闲的g,如果获取不到则从全局的gFree中批量取一部分,返回一个g

        2. 如果没从gfree列表中取到g,则使用malg()函数创建一个新的g,分配的初始栈空间大小为2K。之后初始化g的栈空间;g.startpc成员赋值成新goroutine要执行的函数;

        3. 设置g的sched结构体,该gobuf类型的结构体包含SP、PC等goroutine调度的寄存器上下文信息;

        4. 把新g的状态更新为_Grunnable;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值