43-Golang中的goroutine!!!
创始人
2024-05-31 14:54:49
0

Golang中的goroutine

    • 进程和线程说明
    • 并发和并行
      • 并发
      • 并行
    • Go协程和Go主线程
      • 案例
      • 小结
    • goroutine的调度机制
      • MPG模式基本介绍
        • MPG模式运行的状态1
        • MPG模式运行的状态2
      • 设置GOlang运行的CPU数
    • 不同 goroutine之间如何通讯
      • 使用全局变量加锁同步改进程序

进程和线程说明

  • 1.进程就是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位
  • 2.线程是进程的一个执行实例,是程序执行的最小单元,它是比进程更小的能独立运行的基本单位
  • 3.一个进程可以创建和销毁多个线程,同一个进程中的多个线程可以并发执行
  • 4.一个程序知道有一个进程,一个进程至少有一个线程

并发和并行

1、多线程程序在单核上运行,就是并发

2、多线程程序在多核上运行,就是并行

并发

因为是在CPU上,比如都有10个线程,每个线程执行10毫秒(进行轮询操作),从人的角度看,好像这10个线程都在运行,但是从微观上看,在某一个时间点看,其实只有一个线程在执行,这就是并发

并行

因为是在多个CPU上(比如有10个CPU),比如有10个线程,每个线程执行10毫秒(各自在不同的CPU上执行),从人的角度看,这10个线程都在运行,并且从微观上看,在某一个时间点看,也同时有10个线程在执行,这就是并行
在这里插入图片描述

Go协程和Go主线程

1.Go主线程(有程序员直接称为线程/也可以理解成进程):一个Go线程上,可以起多个协程,可以理解为协程是轻量级的线程

2.Go协程的特点

  • 有独立的栈空间
  • 共享程序堆空间
  • 调度由用户控制
  • 协程是轻量级的线程
    在这里插入图片描述

案例

编写一个程序

1、在主线程中(也可以理解成进程)中,开启一个goroutine,改协程每隔1秒输出“hello,world”

2、在主线程中也每隔1秒“hello,golang”,输出10次后,退出程序

3、要求主线程和goroutine同时执行

4、画出主线程和协程执行流程图

package mainimport ("fmt""strconv""time"
)func test() {for i := 1; i <= 10; i++ {fmt.Println("test () hello,world" + strconv.Itoa(i))time.Sleep(time.Second)}
}func main() {go test() //开启了一个协程for i := 0; i <= 10; i++ {fmt.Println("main() hello,golang" + strconv.Itoa(i))time.Sleep(time.Second)}
}
/*
main() hello,golang0
test () hello,world1
test () hello,world2
main() hello,golang1
main() hello,golang2
test () hello,world3
test () hello,world4
main() hello,golang3
main() hello,golang4
test () hello,world5
test () hello,world6
main() hello,golang5
main() hello,golang6
test () hello,world7
test () hello,world8
main() hello,golang7
main() hello,golang8
test () hello,world9
main() hello,golang9
test () hello,world10
main() hello,golang10*/

在这里插入图片描述

小结

  • 1、主线程是一个物理线程,直接作用在CPU上的。是重量级的,非常消耗CPU资源
  • 2、协程从主线程开启的,是轻量级的线程,是逻辑态。对资源消耗相对小
  • 3、Golang的协程机制时重要的特点,可以轻松的开启上万个协程。其他编程语言的并发机制时一般基于线程的,开启过多的线程,资源耗费大,这里就突显Golang在并发上的优势了

goroutine的调度机制

MPG模式基本介绍

在这里插入图片描述

MPG模式运行的状态1

  • 1、当前程序有三个M,如果三个M都在一个CPU运行,就是并发,如果在不同的CPU运行就会并行
  • 2、M1,M2,M3正在执行一个G,M1的协程队列有三个,M2的协程队列有三个,M3的协程队列有两个
  • 3、从下图可以看到:Go的协程是轻量级的线程,是逻辑态的,Go可以容易的起上万个协程
  • 4、其他程序c/java的多线程,往往是内核态的,比较重量级,几千个线程可能耗光CPU

在这里插入图片描述

MPG模式运行的状态2

  • 1、分两部分来看
  • 2、原来的情况是M0主线程正在执行Go协程,另外有三个协程在队列等待
  • 3、如果Go协程阻塞,比如读取文件或者数据库等
  • 4、这时就会创建M1主线程(也可能是从已有的线程池中取出M1),并且将等待的3个协程挂到M1下开始执行,M0的主线程下的Go任然执行文件io的读写
  • 5、这样的MPG调度模式,可以既让GO执行,同时不会让队列的其他协程一直阻塞,任然可以并发/并行执行
  • 6、等到GO不阻塞了,M0会被放到空闲的主线程继续执行(从已有的线程池中取),同时GO又会被唤醒

在这里插入图片描述

设置GOlang运行的CPU数

介绍:为了充分利用多CPU的优势,在golang中,设置运行的CPU数目

1.go1.8后默认让程序运行在多个核上,可以不用设置了

2.go1.8前,要设置以下,可以更高效的利用CPU

package mainimport ("fmt""runtime"
)func main() {//获取当前系统CPU数量num := runtime.NumCPU()//这里设置num-1的CPU运行go程序runtime.GOMAXPROCS(num)fmt.Println("num=", num)
}
//num=8

不同 goroutine之间如何通讯

1、全局变量加锁同步

2、channel

使用全局变量加锁同步改进程序

  • 因为没有对全局变量m加锁,因此会出现资源争夺问题,代码会出现错误,提升concurrent map writes
  • 解决方案:加入互斥锁
  • 数的阶乘很大,结果会越界,可以将求阶乘改成sum += uint64(i)
    在这里插入图片描述
    在这里插入图片描述

相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...