12 03 2022

第十五章、goroutine和channel

        一、基本介绍

            1.1、什么是并行?

            在同一“时刻”,多件事情一起做;多线程程序在多核上运行,就是并行。特点:多个任务作用在多核CPU上,从微观的角度看,在同一时间点上,有多个任务在同时执行

            1.2、什么是并发?

            多线程程序在单核上运行,就是并发。特点:多个任务作用在一个CPU上;从微观的角度看,在一个时间点上只有一个任务在执行

            1.3、什么是线程?

            线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流。

            1.4、什么是进程?

            进程就是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位,一个进程中可以创建和销毁多个线程,同一个进程中的多个线程可以并发执行,一个程序至少有一个进程,一个进程至少有一个线程。

            可以这么理解进程和线程,启动迅雷软件是一个进程,然后下载很多个电影资源就是多个线程;(程序加载到内存,运行起来就是进程)

            image.png


            1.5、什么是go协程?

            Go主线程(有程序员直接称之为线程/也可以理解成进程),一个Go线程上可以起多个协程,Go 协程可以看作是轻量级线程。与线程相比,创建一个 Go 协程的成本很小。因此在 Go 应用中,常常会看到有数以千计的 Go 协程并发地运行。

            “没有哪个程序是没有进程的”,Go协程的特点:

            1. 有独立的栈空间

            2. 共享程序堆空间

            3. 调度由用户控制

            4. 协程是轻量级的线程


        二、快速入门

            2.1、案例演示

            image.png

            image.png

            2.2、快速入门总结

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

            b、协程是从主线程开启的,是轻量级的线程,是逻辑态的,对资源消耗相对较小

            c、golang的协程是重要的特点,可以轻松开启上万个协程,其他语言的并发机制一般是基于线程的;开启过多的线程,资源耗费大,这里就凸显golang在并发上的优势了

        三、Goroutine调度模型

            3.1、MPG基本模式介绍

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

            P(Processor):协程执行需要的资源(上下文context)

            G(Gorountine):协程,有自己的栈。包含指令指针(instruction pointer)和其它信息(正在等待的channel等等),用于调度。一个P下面可以有多个G

            image.png

            image.png

            3.2、MPG模式运行状态1

            image.png

            3.3、MPG模式运行状态2

            image.png

            3.4、设置golang运行的CPU数

            image.png


        四、channel(管道)

            4.1、完成下面需求

            image.png

            image.png

            执行ceshi.exe 结果如下:

            image.png

            

            存在问题的代码:

            image.png

            4.2、解决办法

            方法一:全局变量加锁同步改进程序

            image.png

            原理:

            image.png

            使用锁会用到的包:

            image.png

            代码改进:

            image.png

            image.png

            image.pngimage.pngimage.png

            方法二:channel通讯机制改进

            4.3、管道基本介绍

            image.png

            image.png

            4.3.1、管道示意:

            image.png

            image.png

            image.png

            4.3.2、管道基本使用

            声明/定义channel:

            var 变量名  chan 数据类型   !!!


            var perChan chan *Person

            var intChan  chan int

            var mapChan chan map[int]string    (用于存放map[int]string类型数据)

            说明:

            1.channel是引用类型

            2.channel必须初始化才能写入数据,即make后才能使用

            3.channel是有类型的,intChan 只能写入int类型数据

            

            演示管道的使用:

            image.png

            image.png

            4.3.3、channel使用注意事项

            a、channel中只能存放指定的数据类型

            b、channel中数据放满了就不能再往里面存放数据了

            c、如果从channel中取出数据以后就可以继续存放

            d、在没有使用协程的情况下,如果channel数据取完了,再取,就会报dead lock


            4.3.4、读写channel案例演示

            image.png

            image.png

            4.3.5、channel的遍历和关闭

            image.png

            image.png

            4.3.5、goroutine和channel协同工作

            需求:完成goroutine和channel协同工作

            1.开启一个writeData协程,向intChan中写入50个数据

            2.开启一个readData协程,从intChan中读取writeData写入的数据.

            注意:writeData和writeData操作的是同一个管道

            3.主线程需要等writeData和writeData协程完成工作才能退出

            image.png

            image.png

            image.png

            4.3.6、goroutine和channel  --  阻塞

            管道容量10,只向管道里面写入数据,写入50个数据,而没有读取,就会出现阻塞而deadlock!

            图1

            image.png

            图2

            image.png

            图3

            image.png

            图4

            image.png

            

            goroutine和channel应用3

            image.png

            思路分析:

            image.png

            代码:

            图一

            image.png

            图二

            image.png

            图三

            image.png


            4.4、channel使用细节和注意事项

            a、channel可以声明为只读,或者只写性质

            image.png

            image.png

            b、使用select可以解决从管道读取数据的阻塞问题

            基本语法:

            image.png

            image.png

            c、goroutine中使用recover, 解决协程中出现panic,导致程序崩溃的问题

            错误代码:

            image.png

            defer + recover

            image.png

            image.png