一、过程和线程
- 过程就是程序在操作系统中的一次执行过程,是零碎进行资源分配和调度的根本单位
- 线程是过程的一个执行实例,是程序执行的最小单元,它是比过程更小的能独立运行的根本单位
- 一个过程能够创立和销毁多个线程,同一个过程中的多个线程能够并发执行
- 一个程序至多有一个过程,一个过程至多有一个线程
二、并发和并行
- 多线程程序在单核上运行,就是并发
- 多线程程序在多核上运行,就是并行
并发 :在一个 cpu 中,比方 10 个线程,每个线程执行 10 毫秒(进行轮询操作),从人的角度看,如同 10 个线程都在运行,但从宏观上看,某一时间点看,其实只有一个线程在执行,这就是并发。
并行 :在多个 cpu 中(如 10 个),比方 10 个线程,每个线程执行 10 毫秒(各自在不同 cpu 上执行),从人的角度看,10 个线程都在运行,但从宏观上看,某一时间点看,也同时 10 个线程在执行,这就是并行。
三、go 协程和主线程
go 主线程是一个物理线程,间接作用在 CPU 上,是重量级的,十分耗 cpu 资源,一个 go 线程上能够起多个协程。
协程是主线程开启的,轻量级的线程,逻辑态的,对资源耗费小
go 协程特点:
- 有独立的栈空间
- 共享程序的堆空间
- 调度由用户管制
- 协程是轻量级的线程
四、channel(管道)
- channel 实质是一个数据结构 - 队列
- 数据是先进先出
- 线程平安,多 goroutine 拜访时,不须要加锁,就是说 channel 自身是线程平安的
- channel 是由类型的,一个 string 的 channel 只能寄存 string 类型的数据
- 遍历时,如果 channel 没有敞开,则会呈现 deadlock 谬误,
如果 channel 曾经敞开,则会失常遍历数据,遍历结束后,就会退出遍历
细节: 管道可申明为只读或只写
var cha1 chan int // 可读可写
var cha2 chan<- int // 只写
var cha2 <-chan int // 只读
应用 select 能够解决从管道取数据的阻塞问题
// 理论开发中,不好确定什么时候敞开该管道
// 可用 select 解决
for {
select {
// 如果管道始终没敞开,不会始终阻塞而 deadlock
// 会主动到下一个 case 匹配
case v := <-intChan:
fmt.Printf("读取数据")
case v := <-stringChan:
fmt.Printf("读取数据")
default:
fmt.Printf("都取不到")
}
}
goroutine 中应用 recover, 解决协程中呈现的 panic,导致程序解体