Go之gorouting 高并发实现

本文详细探讨了Go语言中协程(goroutine)的概念及其在并发编程中的应用。通过对比进程与线程,阐述了协程的优势,包括轻量级、高效资源利用以及并发与并行的区别。并通过代码示例展示了协程的使用方法,以及Go语言如何通过其独特的MPG调度模式实现高效的并发执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一:gorouting的必要性

假如设计一个程序1-10000000000000数字之间那些是偶数

①:传统思路上设计一个循环,在循环中判断

②:使用并发或者并行的方法,将判断那些书偶数的任务分配给多个grouting去完成,这样将大大提高速率。

 二:进程与线程

①:进程就是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位;

②:线程是进程的一个执行实例,是程序执行的最小单位,他是比进程更小的能独立运行的基本单位;

③:一个进程可以创建和销毁多个线程,同一个进程中的多个线程可以并发执行;

④:一个程序至少有一个进程,一个进程至少有一个线程;

⑤:举例说明,在电脑上启动百度云客户端就是启动一个百度云进程,当利用百度云客户端下载一个文件时,就会创建一个下载线程,当下载10个文件时就会创建10个下载线程。

三:并发和并行

①:多线程程序在单核cpu上运行就是并发;

②:多线程程序在多核cpu上运行就是并行;

③:示意图

四:Go协程和Go主线程

 Go主线程(也可以理解为进程),一个Go线程可以有多个协程。

①:Go协程的特点:有独立的栈空间、共享程序堆空间、调度由用户控制、协程是轻量级的线程

②:原理示意图

五:gorouting使用举例

①:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

package main

 

import (

    "fmt"

    "strconv"

    "time"

)

func gr() {

    for i := 1; i <= 3; i++{

        fmt.Println("hello gr"+strconv.Itoa(i))

        time.Sleep(time.Nanosecond)

    }

}

 

func main() {

    go gr()

    for i := 1; i <= 3; i++{

        fmt.Println("hello main"+strconv.Itoa(i))

        time.Sleep(time.Nanosecond)

    }

}

结果

[ `go run gorouting.go` | done ]

    hello main1

    hello gr1

    hello gr2

    hello main2

    hello main3

    hello gr3

 由有代码可知main主线程和gr()协程同时执行

②:主线程与协程原理图

③:总结

主线程是一个物理线程,直接作用在cpu上,是重量级的,非常耗费资源;

协程从主线程开启,是轻量级的线程,是逻辑态。资源耗费较小;

golang的协程机制是重要特点,可以轻松的开启上万个协程,其他语言并发机制一般是基于线程的,开启过多线程会导致资源耗费大。

六:gorouting的MPG的调度模式

①:基本介绍

M:操作系统的主线程(物理线程)

P:协程执行树妖的条件(如是否有足够的cpu资源等等)

G:协程

②:MPG的第一种运行状态

当前有三个M,如果三个M在同一个cpu运行,就是并发,如果在不同cpu运行就是并行;

M1,M2,M3正在执行一个协程G,M1的协程队列有三个协程等待调用执行,M2同M2,M3有两个

由上图可知Go协程是轻量级的线程,是逻辑态,Go可以轻松起上上万协程

其他编程c/java的多线程,往往是内核的,比较重量级,几千个就可能耗光cpu资源

③:MPG的第二种运行状态

M0主线程正在执行G哦协程,另外三个协程在队列等待被执行;

如果G0即正在执行的协程阻塞,如读出数据库等;

这时就会创建M1主线程(也可能是从已有的线程池中取出M1),并且将在等待的3个协程挂到M1上并开始执行,M0的主线程任然执行G0;

这样的MPG调度模式既可以让G0继续执行,又不会让队列的其他协程一直被阻塞,任然可以并发或并行执行;

等到G0执行完毕,M0会被放到空闲的主线程或继续执行其他协程

七:设置Go的运行cpu数

①:go1.8后,默认程序运行在多个核上。

②:go1.8前,默认只运行在一个核,需要设置才可以更高效的利用cpu

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

package main

import (

    "fmt"

    "runtime"

)

func main() {

    //获取当前系统cpu的数量

    num := runtime.NumCPU()

    //设置go运行程序的核实

    runtime.GOMAXPROCS(num)

    fmt.Println("cpu核数:",num)

}

结果

[ `go run gorouting.go` | done ]

    cpu核数: 4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值