\n\n而Go语言采用的是另一个思路:有几个核就跑几个线程,只是某个线程上面有很多协程;协程的切换是不会像线程切换那样有操作系统层面上的开销的,例如线程切换需要切换虚拟地址空间、切换内核栈、切换硬件上下文、CPUcache需要失效,而切换协程完全没有这些开销。\n\n协程底层的实现原理:基于GMP模型:\n\nG:goroutines 表示一个协程\n\nM:machine 表示一个线程\n\nP:processor 管理器,通过队列管理协程\n\n\n\n基于GMP模型,协程运行在线程上\n\n一个协程中的信息:运行栈+寄存器数值(PC,BP,SP)\n\n协程的切换,仅仅需要改变寄存器的数值,cpu便会从需要切换的协程指定位置继续运行\n\n协程与线程的比例关系:N:M\n\n协程:线程\t含义\t优点\t缺点\n1:1\t一个协程在一个线程上运行(其实就是传统的多线程)\t利用多核\t上下文切换比较慢(reactor模型,代价较大)\nN:1\t多个协程在一个线程上运行\t上下文切换较快\t1.无法充分利用多核2.饥饿,如果一个协程不结束,其余协程阻塞\nN:M\t多个协程在多个线程上运行\t充分利用多核,上下文切换快\t对实现要求更高\n协程调度器的设计策略(减少开销、兼顾公平):\n\n复用线程(避免频繁的创建、销毁线程,而是对线程的复用)\n\nwork stealing机制:当本线程无可运行的协程时,尝试从其他线程绑定的P偷取G,而不是销毁线程。\n\nhand off机制:当本线程因为G进行系统调用阻塞时,线程释放绑定的P,把P转移给其他空闲的线程执行。\n\n利用并行:GOMAXPROCS设置P的数量\n\n抢占:限制协程执行时长,不会出现饿死现象\n\n全局协程队列:多个线程全满时可以塞入全局协程队列,它是链表实现的,可以塞很多协程,不用怕没地方放协程。\n\n\n\n常用的同步控制机制:WaitGroup\n\n开发过程中,经常遇到多task之间的同步问题。例如,多个子task并发完成一部分任务,主task等待他们最后结束。\n\nvar wg sync.WaitGroup ;\n \nfor i := 0;i\u003C3;i++ {\n \n wg.Add(1)\n \n go func(i int){\n \n wg.Done()\n \n }(i)\n \n}\n \nwg.Wait()\n管道(Channel)