### 进程和线程介绍

### 程序、进程和线程的关系示意图

### 并发和并行
1) 多线程程序在单核上运行,就是并发
2) 多线程程序在多核上运行,就是并行
3) 示意图:


### **Go 协程和 Go 主线程**
Go 主线程(有程序员直接称为线程/也可以理解成进程): 一个 Go 线程上,可以起多个协程,你可以这样理解,协程是轻量级的线程\[编译器做优化\]。
Go 协程的特点
1) 有独立的栈空间
2) 共享程序堆空间
3) 调度由用户控制
4) 协程是轻量级的线程

### **goroutine-快速入门**
1) 在主线程(可以理解成进程)中,开启一个 goroutine, 该协程每隔 1 秒输出 "hello,world"
2) 在主线程中也每隔一秒输出"hello,golang", 输出 10 次后,退出程序
3) 要求主线程和 goroutine 同时执行.
4) 画出主线程和协程执行流程图


1) 主线程是一个物理线程,直接作用在 cpu 上的。是重量级的,非常耗费 cpu 资源。
2) 协程从主线程开启的,是轻量级的线程,是逻辑态。对资源消耗相对小。
3) Golang 的协程机制是重要的特点,可以轻松的开启上万个协程。其它编程语言的并发机制是一
般基于线程的,开启过多的线程,资源耗费大,这里就突显 Golang 在并发上的优势了
### **goroutine 的调度模型**



### **设置 Golang 运行的 cpu 数**
为了充分了利用多 cpu 的优势,在 Golang 程序中,设置运行的 cpu 数目

## **channel(管道)-看个需求**
需求:现在要计算1-200的各个数的阶乘,并且把各个数的阶乘放入到map中。最后显示出来。要求使用goroutine完成




## **不同 goroutine 之间如何通讯**
1)全局变量的互斥锁
2)使用管道channel来解决
## **使用全局变量加锁同步改进程序**
因为没有对全局变量m加锁,因此会出现资源争夺问题,代码会出现错误,提示concurrent map writes
解决方案:加入互斥锁 ?我们的数的阶乘很大,结果会越界,可以将求阶乘改成sum+=uint64(i)
代码改进


#### **为什么需要channel**
1)前面使用全局变量加锁同步来解决goroutine的通讯,但不完美 2)主线程在等待所有goroutine全部完成的时间很难确定,我们这里设置10秒,仅仅是估算。 3)如果主线程休眠时间长了,会加长等待时间,如果等待时间短了,可能还有goroutine处于工作
状态,这时也会随主线程的退出而销毁
4)通过全局变量加锁同步来实现通讯,也并不利用多个协程对全局变量的读写操作。
5)上面种种分析都在呼唤一个新的通讯机制\-channel