### 进程和线程介绍
![](https://i.vgy.me/2HDsER.png)
### 程序、进程和线程的关系示意图
![](https://i.vgy.me/OKvn4K.png)
### 并发和并行
1) 多线程程序在单核上运行,就是并发
2) 多线程程序在多核上运行,就是并行
3) 示意图:
![](https://i.vgy.me/WWtJp7.png)
![](https://i.vgy.me/koOlb7.png)
### **Go 协程和 Go 主线程**
Go 主线程(有程序员直接称为线程/也可以理解成进程): 一个 Go 线程上,可以起多个协程,你可以这样理解,协程是轻量级的线程\[编译器做优化\]。
Go 协程的特点
1) 有独立的栈空间
2) 共享程序堆空间
3) 调度由用户控制
4) 协程是轻量级的线程
![](https://i.vgy.me/LQY2em.png)
### **goroutine-快速入门**
1) 在主线程(可以理解成进程)中,开启一个 goroutine, 该协程每隔 1 秒输出 "hello,world"
2) 在主线程中也每隔一秒输出"hello,golang", 输出 10 次后,退出程序
3) 要求主线程和 goroutine 同时执行.
4) 画出主线程和协程执行流程图
![](https://i.vgy.me/St8mfO.png)
![](https://i.vgy.me/T1WLji.png)
1) 主线程是一个物理线程,直接作用在 cpu 上的。是重量级的,非常耗费 cpu 资源。
2) 协程从主线程开启的,是轻量级的线程,是逻辑态。对资源消耗相对小。
3) Golang 的协程机制是重要的特点,可以轻松的开启上万个协程。其它编程语言的并发机制是一
般基于线程的,开启过多的线程,资源耗费大,这里就突显 Golang 在并发上的优势了
### **goroutine 的调度模型**
![](https://i.vgy.me/p6IMYy.png)
![](https://i.vgy.me/RPtg3v.png)
![](https://i.vgy.me/0FqzFj.png)
### **设置 Golang 运行的 cpu 数**
为了充分了利用多 cpu 的优势,在 Golang 程序中,设置运行的 cpu 数目
![](https://i.vgy.me/lJRcGP.png)
## **channel(管道)-看个需求**
需求:现在要计算1-200的各个数的阶乘,并且把各个数的阶乘放入到map中。最后显示出来。要求使用goroutine完成
![](https://img.kancloud.cn/7f/ca/7fca43ebdbe0663d6cb9680c59b76cac_725x653.png)
![](https://img.kancloud.cn/29/19/2919148bcd5d819bafd119300761fb6f_725x766.png)
![](https://img.kancloud.cn/f2/90/f290ea43226aba556f0b44611a7cac07_694x307.png)
![](https://img.kancloud.cn/08/6a/086a2eb9908412d44f5a425fb28f6659_727x357.png)
## **不同 goroutine 之间如何通讯**
1)全局变量的互斥锁
2)使用管道channel来解决
## **使用全局变量加锁同步改进程序**
因为没有对全局变量m加锁,因此会出现资源争夺问题,代码会出现错误,提示concurrent map writes
解决方案:加入互斥锁 ?我们的数的阶乘很大,结果会越界,可以将求阶乘改成sum+=uint64(i)
代码改进
![](https://img.kancloud.cn/a4/e8/a4e889c934dcc3e179b01181b7ec7321_705x531.png)
![](https://img.kancloud.cn/fc/1d/fc1d5e5e5365206c1d2c5130b4f05978_702x163.png)
#### **为什么需要channel**
1)前面使用全局变量加锁同步来解决goroutine的通讯,但不完美 2)主线程在等待所有goroutine全部完成的时间很难确定,我们这里设置10秒,仅仅是估算。 3)如果主线程休眠时间长了,会加长等待时间,如果等待时间短了,可能还有goroutine处于工作
状态,这时也会随主线程的退出而销毁
4)通过全局变量加锁同步来实现通讯,也并不利用多个协程对全局变量的读写操作。
5)上面种种分析都在呼唤一个新的通讯机制\-channel