设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间02 现在时间02 缓存数据 你要知道这个世界上没有人会突然不爱你 只是你突然发现了而已

你要知道这个世界上没有人会突然不爱你 只是你突然发现了而已 -- 朗朗晴天

查看: 1190|回复: 2

Go语言中的并发goroutine底层原理

[复制链接]

  离线 

TA的专栏

  • 打卡等级:即来则安
  • 打卡总天数:18
  • 打卡月天数:1
  • 打卡总奖励:259
  • 最近打卡:2025-07-05 23:30:44
等级头衔

等級:晓枫资讯-上等兵

在线时间
0 小时

积分成就
威望
0
贡献
416
主题
384
精华
0
金钱
1473
积分
836
注册时间
2023-2-10
最后登录
2025-7-5

发表于 2024-3-12 13:34:13 | 显示全部楼层 |阅读模式
目录


  • 一、基本概念

    • ①并发、并行区分
    • ②从用户态线程,内核态线程阐述go与java并发的优劣
    • ②高并发为什么是Go语言强项?
    • ③Go语言实现高并发底层GMP模型原理解析

  • 二、上代码学会Go语言并发

    • ①.开启一个简单的线程
    • ②.动态的关闭线程


一、基本概念


①并发、并行区分

1.概念

  • 并发:同一时间段内一个对象执行多个任务,充分利用时间
  • 并行:同一时刻,多个对象执行多个任务
2.图解
类似于超市柜台结账,并行是多个柜台结多个队列,在计算机中是多核cpu处理多个go语言开启的线程,并发是一个柜台结账多个队列,在计算机中就是单核cpu处理多个任务,抢夺时间片.
1.png


②从用户态线程,内核态线程阐述go与java并发的优劣

1.用户态线程、内核态线程差异

  • 用户态:只能受限制的访问内存,且不允许访问外围设备,占用CPU资源可以被其他程序抢走。
  • 内核态:CPU可以访问内存所有数据,包括外围设备,例如硬盘网卡等,cpu可以将自己从一个程序切换到另一个程序
2.java与go并发差异:
java:

  • java没有规定具体使用什么线程,而是在不同形态的线程上进行切换,会耗费相当的资源
  • go是用户态线程,资源耗费较少,一个线程的栈体默认为1M,并且需要运行在JVM上
go:

  • go语言并发通过,goroutine实现,属于用户态的线程,可以根据需要创建成千上万个goroutine,每个goroutine占用内存大小会根据需要动态生成,典型的大小为2kB可以按需求放大到1GB,在go语言中一次可以轻松创建十万左右的goroutine,并且不依赖运行环境。

②高并发为什么是Go语言强项?

1.历史背景
Go语言产生较晚,在其产生之前就已经有了多核cpu,所以设计者的理念就是将这门新的语言使用到多核cpu上支持更大数量级的并发
2.自身原因
    Go语言多并发底层实现使用的是协程,他占有更少的资源具有更快的执行速度,占用的资源还会根据 任务量进行扩大或者缩小

③Go语言实现高并发底层GMP模型原理解析

1. G:
G是
  1. Goroutine
复制代码
的缩写,在这里就是
  1. Goroutine
复制代码
的控制结构,是对Goroutine的抽象。其中包括执行的函数指令及参数;G保存的任务对象;线程上下文切换,现场保护和现场恢复需要的寄存器(SP、IP)等信息。在 Go 语言中使用 runtime.g 结构表示。
2. M:
表示操作系统线程也可以称为内核线程,由操作系统调度以及管理,调度器最多可以创建 10000 个线程,在 Go 语言中使用
  1. runtime.m
复制代码
结构表示。(用户线程与内核线程的映射关系)
3. P:
调度各个
  1. goroutine
复制代码
,使他们之间协调运行逻辑处理器,但不代表真正的CPU的数量,真正决定并发程度的是P,初始化的时候一般会去读取
  1. GOMAXPROCS
复制代码
对应的值,如果没有显示设置,则会读取默认值,在Go1.5之后GOMAXPROCS被默认设置可用的核数,而之前则默认为1,在 Go 语言中使用 runtime.p 结构表示。
4.指定cpu线程个数
通过
  1. runtime.GOMAXPROCS()
复制代码
,可以指定P的个数,如果没有指定则默认跑满整个cpu

二、上代码学会Go语言并发


①.开启一个简单的线程

    开启线程使用go+函数,以下案例要认识到开启多线程使用函数闭包可能会出现的问题
1.使用匿名函数开启线程
  1. //打印1-1000
  2.     for i := 0; i < 1000; i++ {
  3.         go func() {
  4.             fmt.Println(i)
  5.         }()
  6.     }
  7. //这里使用了函数闭包
  8. /*
  9. 打印结果
  10.     995
  11.     995
  12.     995
  13.     996
  14.     996
  15.     999
  16.     1000
  17.     1000
  18. */
复制代码
2.出问题的原理:
匿名函数进行操作时会将当前环境内的变量进行闭包,由于启动线程需要一定时间在启动线程的时候i进行了改变所以打印的时候会有许多值相同

②.动态的关闭线程

1.为什么需要进行动态的关闭线程?
    在Go语言中如果不进行动态的关闭线程,那么有可能在子线程没有执行结束主线程就结束了,那样的话会有 程序安全隐患,所以主线程不可以直接结束,应作为后盾,直到所有线程都结束了才可以结束。
2.使用waitGroup
waitGroup有三个方法常用:

    1. waitGroup.Add()
    复制代码
    :使用wait计数器记1次数//将创建的线程数传进去
    1.  waitGroup.Done()
    复制代码
    :wait计数器减1(放在被开启线程的函数内)
    1. waitGroup.Wait()
    复制代码
    :阻塞等待wait计数器值为零(放在主线程内)
  1. defer
复制代码
是在函数主体执行完的时候执行的代码(可理解为延时执行)
代码如下:
  1. package main

  2. import (
  3.     "fmt"
  4.     "math/rand"
  5.     "sync"
  6.     "time"
  7. )
  8. // 定义一个waitGroup结构体变量
  9. var wg sync.WaitGroup

  10. func f(i int) {
  11.     // 等到函数执行完毕,会将waitGroup内的计数器减一
  12.     defer wg.Done()
  13.     rand.Seed(time.Now().UnixNano())
  14.     time.Sleep(time.Duration(rand.Intn(3)) * time.Second)
  15.     fmt.Println(i)
  16. }
  17. func main() {
  18.     for i := 0; i < 100; i++ {
  19.         // 开启一个线程就使用waitGroup记一次数
  20.         wg.Add(1)
  21.         go f(i)
  22.     }
  23.     // 阻塞等待waitGroup计数器为0
  24.     wg.Wait()
  25.     fmt.Println("hello")
  26. }
复制代码
总结:
Go语言的高并发奠定了其未来在高级语言中的地位,越来越多的用户加入互联网需要一个支持高并发语言的支持,亿万级电商秒杀,亿万级游戏用户同时在线都离不开这样的语言,所以Go语言一直被游戏后端、web后端项目开发者青睐。
到此这篇关于Go语言中的并发goroutine底层原理的文章就介绍到这了,更多相关Go语言中的并发goroutine内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

  • 打卡等级:即来则安
  • 打卡总天数:25
  • 打卡月天数:1
  • 打卡总奖励:363
  • 最近打卡:2025-07-10 20:12:12
等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
423
积分
57
注册时间
2023-1-4
最后登录
2025-7-10

发表于 2024-11-17 15:45:58 | 显示全部楼层
感谢楼主,顶。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
11
积分
2
注册时间
2023-10-31
最后登录
2023-10-31

发表于 2025-3-26 12:22:43 | 显示全部楼层
顶顶更健康!!!
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1楼
2楼
3楼

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表