goroutine 简单使用
package main
import (
"fmt"
"strconv"
"time"
"runtime"
)
/**
知识储备
1) 进程就是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位
2)线程是进程的一个执行实例.是程序执行的最小但愿,它是比进程更小的能独立运行的基本单元
3)一个进程可以创建和销毁多个线程,同一个进程中的多个线程可以并发执行
4) 一个程序至少有一个进程,一个进程至少由一个线程
并发和并行
1 多线程程序在单核上运行,就是并发
并发特点:
1.1 多个任务作用在一个cpu
1.2 从微观角度看,在一个时间点上,其实只有一个任务在执行
2 多线程程序在多核上运行就是并行
并行的特点:
2.1多个任务在多个cpu
2.2 从微观角度看,在一个时间点上,就是多个任务在同时执行
2.3 这样看来,并行的速度快
总结:
并发: 因为是在一个CPU上,比如10个线程,每个线程执行10毫秒(进行轮询操作)从人的角度看,
好像这个10个线程都在运行,但是从微观上看,在某一个时间点看,其实只有一个线程在执行,这就是并发
并行: 以为是在多个CPU上(比如10个CPU).比如有10个线程,每个线程执行10毫秒(各自在不同cpu上执行),
从人的角度看,这10个线程都在运行,但是从微观上看.在某一个时间点上看,也同时有10个线程在执行,这就是并行
GO 协程 与 GO 主线程
Go 主线程(有程序员称为线程/也可以理解为进程):
一个GO线程上,可以起多个协程,你可以这样理解,协程是轻量级的线程[编译器做优化]
Go协程特点:
1) 独立的栈空间
2) 共享程序堆空间
3)调度是用户控制
4)协程是轻量级的线程
*/
/**
1)在主线程(可以理解成进程)中,开启一个goroutine,该协程每隔1妙输出"hello,world"
2) 在主线程也每隔一秒输出"Hello Golang",输出10次之后退出程序
3) 要求主线程和goroutine同时执行
4)画出主线程和协程执行流程图
*/
func test() {
for i:=1;i<=10 ;i++ {
fmt.Println("test() hello World "+strconv.Itoa(i))
time.Sleep(time.Second)
}
}
func main() {
go test() // 开启了一个协程
// 1)如果主线程 退出了,协程即使还没有执行完也会退出
// 2)当然协程也可以再生主线程没有推出前,就自己结束了,比如完成了自己任务
for i:=1; i<=10;i++ {
fmt.Println("main() Hello GO GO "+strconv.Itoa(i))
time.Sleep(time.Second)
}
/**
总结:
1)主线程是一个物理线程,直接作用在CPU上,是重量级 的,非常消耗CPU
2) 协程从主线程开启的,是轻量级的线程,是逻辑态,对资源消耗小
3)Golang的协程机制是重要的特点,可以轻松开启上万个协程.其他编程语言的并发机制是一般基于线程的,
开启过多的线程,消耗资源大,这里是Golang的优势
MPG 模式:
1) M :操作系统的主线程(是物理线程)
2) P: 协程执行需要的上下文
3)G: 协程
MPG 模式运行的状态1
1)当前程序有三个M ,如果三个M都在一个CPU上运行,就是并发,如果在不同的CPU运行就是并行
2)M1 M2 M3 正在执行一个G,M1的协程队列有三个,M2协程队列有三个,M3的协程队列有2个
3) 从中可看出Go的协程是轻量级的线程,是逻辑态的,GO可以容易的起上万个协程
4) 其他程序c/Java 往往是内核态的,比较重量级,几千个线程可能消耗CPU
MPG 模式运行的状态2
1) 分成两个部分来看
2) 原来的情况是M0 是主线程正在执行GO协程,另外有三个协程在队列等待
3)如果Go协程阻塞,比如读取文件或者数据库等
4)这时就会创建M1 主线程(也可能是从已有的线程池中取出M1),并且将等待的3个协程挂到M1 下开始执行,
M0 的主线程下的GO仍然执行文件IO的读写
5)这样的MPG调度模式,可以揖让GO执行,同时也不会让队列其他协程一直阻塞,仍然可以并发/并行执行
6)等到Go不阻塞了M0 会被放到空闲的主线程继续执行(从已有的线程池中取),同时Go又会背唤醒
*/
// Golang 为了充分利用CPU的优势,在Golang程序中,设置运行的CPU数目
// 获取当前系统的CPU的数量
num:=runtime.NumCPU()
// 这里设置num-1 的CPU的go程序
runtime.GOMAXPROCS(num)
fmt.Println("num=",num) // 可以检查你的CPU核数是多少
//go 1.8,默认程序运行在多核上,可以不用设置了
//go1.8 前,还是要设置一下,可以高效的利用CPU
}