一、过程和线程
- 过程就是程序在操作系统中的一次执行过程,是零碎进行资源分配和调度的根本单位
- 线程是过程的一个执行实例,是程序执行的最小单元,它是比过程更小的能独立运行的根本单位
- 一个过程能够创立和销毁多个线程,同一个过程中的多个线程能够并发执行
- 一个程序至多有一个过程,一个过程至多有一个线程
二、并发和并行
- 多线程程序在单核上运行,就是并发
- 多线程程序在多核上运行,就是并行
并发 :在一个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,导致程序解体