首页  

Goroutine与线程的区别     所属分类 go 浏览量 401
进程  线程  协程 goroutine  调度 
线程是操作系统 进行运算调度的最小单位
Goroutine是建立在线程之上的轻量级的抽象
相比于线程,它的创建和销毁的代价要小很多,并且它的调度是独立于线程的

线程分为了“内核态”线程和“用户态”线程
“用户态”线程必须绑定“内核态”线程,CPU并不知道有“用户态”线程的存在,它只知道它运行的是一个“内核态”的线程
内核线程叫“线程”,“用户态”线程叫做“协程”



package main

import ( 
    "fmt" 
    "time"
)

func learning() {
     fmt.Println("My first goroutine")
}

func main() {
     // 使用go关键字,在一个新的gorutine中运行learning()
     go learning() 
     // 让主函数sleep一秒,防止在gorutine还未完成前 结束 
     time.Sleep(1 * time.Second)
     fmt.Println("main function")
}

和线程一样,golang的主函数,跑在一个goroutine中
如果主goroutine结束了,其它的goroutine都会结束

Goroutine 并不会更快,它只是提高了程序的并发性能
golang的scheduler会调度其它可以执行的goroutine运行

 
内存消耗更少  Goroutine 2KB  ,线程 1mb 
创建与销毁的开销更小
  线程创建时需要向操作系统申请资源,销毁时归还资源,goroutine 的创建和销毁 由go语言在运行时自己管理
切换开销更小
  线程调度方式 抢占式 
  在线程切换的过程中需要保存/恢复所有的寄存器信息,比如十六位通用寄存器,PC(Program Counter),SP(Stack Pointer),段寄存器等
  goroutine 调度 协同式 ,不会直接与操作系统内核打交道 ,goroutine 切换,只有少量的寄存器需要保存和恢复(PC和SP)

go调度是协作+抢占,协作点可以主动让出 运作时间太久会被抢断 ? (待确认)


Goroutine的调度 调度器会在以下几个时间点对其进行切换 Channel接受或者发送会造成阻塞的消息 当一个新的goroutine被创建时 可以造成阻塞的系统调用,如文件和网络操作 垃圾回收 Processor(P) OSThread(M) Goroutines(G) 可用的线程数 GOMAXPROCS 默认值是可用的CPU核数 OSThread调度在processor上,goroutines调度在OSThreads上 每个processor有一个本地goroutine队列 ,同时有一个全局的goroutine队列 每个OSThread都会被分配给一个processor ,最多只能有GOMAXPROCS个processor, 每个processor同时只能执行一个OSThread ,Scheculer可以根据需要创建OSThread 在每一轮调度中,scheduler找到一个可以运行的goroutine并执行直到其被阻塞
java 虚拟线程使用 java Virtual Threads 虚拟线程

上一篇     下一篇
Redis 性能监控指标

JVM知识点汇总

go压测工具 go-stress-testing

go 多模块例子

go开源工具库 lancet

华为笔记本触摸板使用技巧