第十五章、goroutine和channel
一、基本介绍
1.1、什么是并行?
在同一“时刻”,多件事情一起做;多线程程序在多核上运行,就是并行。特点:多个任务作用在多核CPU上,从微观的角度看,在同一时间点上,有多个任务在同时执行
1.2、什么是并发?
多线程程序在单核上运行,就是并发。特点:多个任务作用在一个CPU上;从微观的角度看,在一个时间点上只有一个任务在执行
1.3、什么是线程?
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流。
1.4、什么是进程?
进程就是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位,一个进程中可以创建和销毁多个线程,同一个进程中的多个线程可以并发执行,一个程序至少有一个进程,一个进程至少有一个线程。
可以这么理解进程和线程,启动迅雷软件是一个进程,然后下载很多个电影资源就是多个线程;(程序加载到内存,运行起来就是进程)
1.5、什么是go协程?
Go主线程(有程序员直接称之为线程/也可以理解成进程),一个Go线程上可以起多个协程,Go 协程可以看作是轻量级线程。与线程相比,创建一个 Go 协程的成本很小。因此在 Go 应用中,常常会看到有数以千计的 Go 协程并发地运行。
“没有哪个程序是没有进程的”,Go协程的特点:
1. 有独立的栈空间
2. 共享程序堆空间
3. 调度由用户控制
4. 协程是轻量级的线程
二、快速入门
2.1、案例演示
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
3.2、MPG模式运行状态1
3.3、MPG模式运行状态2
3.4、设置golang运行的CPU数
四、channel(管道)
4.1、完成下面需求
执行ceshi.exe 结果如下:
存在问题的代码:
4.2、解决办法
方法一:全局变量加锁同步改进程序
原理:
使用锁会用到的包:
代码改进:
方法二:channel通讯机制改进
4.3、管道基本介绍
4.3.1、管道示意:
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类型数据
演示管道的使用:
4.3.3、channel使用注意事项
a、channel中只能存放指定的数据类型
b、channel中数据放满了就不能再往里面存放数据了
c、如果从channel中取出数据以后就可以继续存放
d、在没有使用协程的情况下,如果channel数据取完了,再取,就会报dead lock
4.3.4、读写channel案例演示
4.3.5、channel的遍历和关闭
4.3.5、goroutine和channel协同工作
需求:完成goroutine和channel协同工作
1.开启一个writeData协程,向intChan中写入50个数据
2.开启一个readData协程,从intChan中读取writeData写入的数据.
注意:writeData和writeData操作的是同一个管道
3.主线程需要等writeData和writeData协程完成工作才能退出
4.3.6、goroutine和channel -- 阻塞
管道容量10,只向管道里面写入数据,写入50个数据,而没有读取,就会出现阻塞而deadlock!
图1
图2
图3
图4
goroutine和channel应用3
思路分析:
代码:
图一
图二
图三
4.4、channel使用细节和注意事项
a、channel可以声明为只读,或者只写性质
b、使用select可以解决从管道读取数据的阻塞问题
基本语法:
c、goroutine中使用recover, 解决协程中出现panic,导致程序崩溃的问题
错误代码:
defer + recover