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)
    在这里插入图片描述
    在这里插入图片描述

相关内容

热门资讯

不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
安卓文字转语音tts没有声音 安卓文字转语音TTS没有声音的问题在应用中比较常见,通常是由于一些设置或者代码逻辑问题导致的。本文将...
APK正在安装,但应用程序列表... 这个问题可能是由于以下原因导致的:应用程序安装的APK文件可能存在问题。设备上已经存在同名的应用程序...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
保存时出现了1个错误,导致这篇... 当保存文章时出现错误时,可以通过以下步骤解决问题:查看错误信息:查看错误提示信息可以帮助我们了解具体...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...