zoukankan      html  css  js  c++  java
  • Golang协程和线程区别

    一.进程、线程、协程介绍

    进程:系统中所有的应用程序都是以进程(process)的方式运行,是系统进行资源分配和调度的基本单位,每个进程都有自己的独立的地址空间,使得进程之间的地址空间相互隔离。

    线程:线程是程序执行流的最小单元上,通常意义上,一个进程由一个到多个线程组成,各个线程之间共享程序的内存空间(包括代码段、数据段、堆等)及一些进程级的资源(如打开的文件和信号)。

    协程:协程在Go语言中,由轻量级线程实现,由Go运行时(runtime)管理。

    这里特别说明下并发和并行:

    • 并发:多线程程序在单核上运行
    • 并行:多线程程序在多核上运行

    二.协程与进程、线程的区别

    1)进程拥有自己的堆栈,不共享堆和栈,是由操作系统进行调度的。
    2)线程拥有自己的独立的栈和共享的堆,也是由操作系统进行调度。
    3)协程共享堆,不共享栈,协程的调度由用户控制。

    三.协程的优点

    1)代码编辑简单,可以将异步处理逻辑代码用同步的方式编写,将多个异步操作集中到一个函数中完成。
    2)单线程模式,没有线程安全的问题,不需要加锁操作。
    3)性能好,协程是用户态线程,切换更加高效。

    四.协程比线程轻量分析

    一旦我们创建完线程,就无法决定它什么时候获得时间片,什么时候让出时间片,这里都交给了内核。和我们编写协程时可以控制,可控的切换时机和很小的切换代价,从操作系统有没有调度权来看,协程就是因为不需要进行内核态的切换。

    1)Go协程调用跟切换比线程效率高
    线程并发执行流程:
    线程是内核对外提供的服务,应用程序可以通过系统调用让内核启动线程,由内核来负责线程调度和切换,线程在等待IO操作时标为unrunnable状态会触发上下文切换。现代操作系统一般采用抢占式调度,上下文切换一般发生在时钟中断和系统调用返回前,调度器计算当前线程的时间片,如果需要切换就从运行队列中选出一个目标线程,保存当前线程的环境,并且恢复目标线程的运行环境,最典型的就是切换ESP指向目标线程内核堆栈,将EIP指向目标线程上次被调度出时的指令地址。
    Go协程并发执行流程:
    不依赖操作系统和其提供的线程,Golang自己实现的CSP并发模型实现:M,P,G
    Go协程也叫用户态线程,协程之间的切换发生在用户态,在用户态没有时钟中断,系统调用等机制,因此效率高。

    2)Go协程占用内存小
    执行Go协程只需要极少的栈内存(大概4~5KB),默认情况下,线程栈的大小为1MB。
    Goroutine就是一段代码,一个函数入口,以及在堆上为其分配的一个堆栈,所以它非常廉价,我们可以很轻松的创建上万个Goroutine,但它们并不是被操作系统所调度执行。

    参考链接:https://chende.ren/2021/10/12151539-go-thread-gmp.html

  • 相关阅读:
    NC20565 生日礼物(双指针)
    NC20566 游戏(二分图)
    NC19833 地斗主(dp+矩阵快速幂)
    CF505C Mr. Kitayuta, the Treasure Hunter(dp)
    HDU5493 Queue(线段树)
    HDU5489 Removed Interval (LIS+分治)
    CF1158C Permutation recovery(线段树优化建图)
    NC20811 蓝魔法师(树形dp)
    NC20857 Xor Path(dfs)
    chrony同步时间
  • 原文地址:https://www.cnblogs.com/yuhaohao/p/15421400.html
Copyright © 2011-2022 走看看