Golang-goroutine

 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

}

 

おすすめ

転載: blog.csdn.net/qq_35361859/article/details/103524287