1.goroutine——看一个需求
需求:要求统计 1-9000000000的数字中,哪些是素数?
分析思路:
1) 传统的方法,就是使用一个循环,循环的判断各个数是不是素数.[很慢]
2) 使用并发或者并行的方式,将统计素数的任务分配给多个goroutine去完成,这时就会使用到goroutine.[速度提高4倍]
2. 进程和线程介绍
1)进程就是程序在操作系统的一次执行过程,是系统进行资源分配和调度的基本单位
2)线程是进程中执行运算的最小单位,是进程中的一个实例,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤销另一个线程,同时一个进程中的多个线程之间可以并发执行。
3)一个进程可以创建和销毁多个进程,同一个进程中的多个线程可以并发执行。
4)一个程序至少有一个进程,一个进程至少有一个线程
3. 程序、进程和线程的关系示意图
4. 并发和并行
1)多线程程序在单核上运行,就是并发
2)多线程程序在多核上运行,就是并行
3)示意图如下:
小结:
1)并发:因为是在一个CPU上,比如有10个线程,每个线程执行10ms(进行轮询操作),从人的角度看,好像这10个进程都在运行,但是从微观上看,在某一个时间点看,其实只有一个线程在执行,这就是并发。
2)并行:因为是在多个CPU上(比如有10个CPU),每个线程执行10ms(各自在不同CPU上执行),从人的角度看,这10个线程都在运行,但是从微观上看,在某一个时间点看,也同时有10个线程在执行,这就是并行。
5. Go协程和Go主线程
Go主线程(有程序员直接称为线程/也可以理解成进程):一个Go线程上,可以起多个协程,写成是轻量级的线程【编译器做优化】
面试必问:Go协程的特点:
1)有独立的栈空间
2)共享程序堆空间
3)调度由用户控制
4)协程是轻量级的线程
示意图:
6. goroutine——快速入门
案例说明:
请编写一个程序,完成如下功能:
1)在主线程(可以理解成进程)中,开启一个goroutine,该协程每隔1秒输出“hello,world”
2)在主线程中也每隔1秒输出"hello,golang",输出10次后,退出程序
3)要求主线程和goroutine同时执行
代码如下:
package main
import (
"fmt"
"strconv"
"time"
)
// 请编写一个程序,完成如下功能:
// 1) 在主线程(可以理解成进程)中,开启一个goroutine,该协程每隔1s输出"hello world"
// 2) 在主线程中也每个1s输出"hello golang",输出10次后退出程序
func test() {
for i := 1; i <= 10; i++ {
fmt.Println("test hello world"+strconv.Itoa(i))
time.Sleep(time.Second)
}
}
func main() {
// test() // 不开启协程,会等test()执行完毕后,再执行下面的for语句
go test() // 开启了一个 协程
for i := 1; i <= 10; i++ {
fmt.Println("main hello golang"+strconv.Itoa(i))
time.Sleep(time.Second)
}
}
4)画出主线程和协程执行流程图
7. 快速入门小结
1)主线程是一个物理线程,直接作用在CPU上的,是重量级的,非常耗费CPU资源。
2)协程从主线程开启,是轻量级的线程,是逻辑态。对资源消耗相对小。
3)Golang的协程机制是重要的特点,可以轻松的开启上万个协程。其它编程语言的并发机制是一般基于线程的,开启过多的线程,资源耗费大,这里就突显Golang在并发上的优势了。
8. MPG模式基本介绍
9.MPG模式运行的状态1
10.MPG模式运行的状态2
11. 设置Golang运行的CPU数量
介绍:为了充分利用多CPU的优势,在Golang程序中,设置运行的CPU数目
1)go1.8后。默认让程序运行在多核上了,不用设置
2)1.8前,需要手动设置Golang运行的CPU数量,可以更高效率使用cpu
package main
import (
"fmt"
"runtime"
)
func main() {
// 获取当前系统 CPU的数量
num := runtime.NumCPU()
// 设置num - 1的cpu运行程序
runtime.GOMAXPROCS(num - 1)
fmt.Println("num=",num)
}