前言:要了解协程和管道首先得了解以下四个概念
进程和线程简单说明
1.进程就是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位
2.线程是进程的一个执行实例,是程序执行的最小单元,它是比进程更小的独立运行的基本单位
3.一个进程可以创建销毁多个线程,同一个进程的多个线程可以并发执行
4.一个程序至少有一个进程,一个进程至少有一个线程
个人理解:把计算机比作一家公司,程序就是这家公司的部门,进程就是公司安排的某个工作内容的完成过程,线程就是部门里处理这个工作内容的人去完成的实例,公司下发工作内容就相当于给部门下发任务,由公司(这里公司就是只CPU,后面会跟并发和并行有关联)来调动相应的人数去处理这个或者这些任务,如有错误请指出,谢谢。
并发和并行
1.多线程程序在单核上运行,就是并发
2.多线程程序在多核上运行,就是并行
个人理解:沿用上一个例子,并发就是有多个任务安排,但是现在部门内部只有一个人,这个人就得同时处理所有工作内容,感觉上是所有的任务都在同时处理,但实际上在一个时间点上,这个人只能处理一个问题,只是在不停地切换不同的任务处理,而非处理完成一个任务后再切换到下一个任务。并行就是部门内部有多个人,可以同时处理多个任务
GO的协程和主线程
1.GO主线程(有程序员直接称为线程/也可以理解成进程),一个GO线程上,可以起多个协程,可以这样理解,协程是轻量级的线程(编译器做优化)。
2.GO协程的特点
- 有独立的栈空间
- 有共享程序堆空间
- 调度由用户控制
- 协程是轻量级的线程
goroutine 快速入门小结
1.主线程是一个物理线程吗,直接作用在cpu上的,是重量级的,非常消耗cpu资源。
2.协程从主线程开启的,是轻量级的线程,是逻辑态的。对资源消耗相对小。
3.Golang的协程机制是重要的特点,可以轻松的开启上万个协程。其他编程语言的并发机制是一般基于线程的,开启过多的线程,资源消耗大,这就突显了Golang在并发上的优势
goroutine的调度模型(MPG模式)
基本介绍
M:操作系统的主线程(是物理线程)
P:协程执行需要的上下文
G:协程
简单来说,就是一个协程阻塞了,会把后续操作自动放到其余空闲的协程中执行,等到阻塞协程完成后,会把剩余的任务又使用该线程继续执行。这样来回切换可以保证阻塞的协程不会影响效率。达成并发/并行的效果
内容较多,需详细了解请自行搜索查询。
Channel(管道)
在协程中进行相互通信时(都要使用同一个全局变量)会产生资源竞争(同时对某一个全局变量进行读写)的问题。
channel用于解决不同的goroutine之间通信的问题,也可以使用加互斥锁的方式来达成这个目的。但互斥锁没这玩意儿好。
基本介绍
1.channel本质就是一个数据结构-队列
2.数据是先进先出,与栈是相反的,栈是先进后出
3.线程安全,多个goroutine访问时,不需要加锁,本身就是线程安全的
4.channel是有类型的,一个string的channel只能存放string类型的数据
定义/声明
var 变量名 chan 数据类型
举例:
var intChan chan int
var stringChan chan string
var structChan chan Struct (结构体)
var mapChan chan map[string]int (map)
channel是一个引用类型,必须初始化才能写入数据,即使用make进行初始化,第二个参数为channel的长度
int类型的管道只能存放int类型的数据
给管道写入数据,拿上面的intChan举例
读取管道中的数据
channel使用的注意事项
1.channel总只能存放指定的数据类型
2.channel的数据放满后就不能再放入
3.如果从channel取出数据后,可以继续放入
4.在没有使用协程的情况下,如果channel的数据取完了,再取就会报dead lock
channel关闭
5.在取值时,实际上会返回两个值,x,ok:=<-chan,第二个值为ok,在成功取出,为false则失败
使用内置函数close可以关闭channel,当channel关闭后,就不能再向channel写数据了,但是仍然可以从该channel读取数据。
channel的遍历
channel支持for-range的方式进行遍历,但注意两个细节
1.在遍历时,如果chanel没有关闭,则会出现deadlock的错误
2.在遍历时,如果channel已经关闭,则会正常遍历数据,遍历完后,就会退出遍历