进程和线程
A)进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单元
B)线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位
C)一个进程可以创建和撤销多个线程,同一个进程中的多个线程之间可以并发执行
nginx是 进程 ----》Fork多个子进程 --》多线程 --》多进程程序
协程和线程
协程:独立的栈空间,共享堆内存,调度由用户自己控制,本质上有点类似于用户级线程,这些用户线程的调度也是自己实现的
线程:一个线程上可以跑多个协程,协程是轻量级的线程
线程分为用户态的线程和操作系统级别的线程
goroutine:
package main
import (
"fmt"
"time"
)
func test(){
var i int
for {
fmt.Println(i)
time.Sleep(time.Second)
i++
}
}
func main(){
go test()
for{
fmt.Println("i running in main")
time.Sleep(time.Second) //必须要加上,防止main线程跑的太快看不清
}
}
执行结果
D:\project>go build go_dev/day8/example
D:\project>example
i running in main
0
1
i running in main
i running in main
2
3
i running in main
i running in main
4
5
i running in main
i running in main
6
goroutine调度模型
M:系统里面的线程
P:调度器
G:协程 goroutine
1)可以看出上面的每个操作系统线程有4个协程执行,只不过有3个协程是在队列中执行
2)可以看出一个线程可以多个协程在跑
在1.8之前可以把程序设置到init函数里面,1.8以上不用设置cpu的核心数
如何设置golang运行的cpu核数
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package main import ( "runtime" "fmt" ) func main(){ num := runtime.NumCPU() //查找当前cpu的核心数量 runtime.GOMAXPROCS(num) //设置golang运行核数 这里结果为8 fmt.Println(num) } 运行结果 8
channel声明
var 变量名 chan 类型
var test chan int
var test chan string
var test chan map[string] string
var test chan stu
var test chan *stu
channl初始化使用make
变量名 = make (chan 类型 size)
创建map类型往channel里面添加数据
创建map类型往channel里面添加数据
package main
func main(){
var mapchan chan map[string]string //声明channel
mapchan = make(chan map[string]string ,10) //初始化channel
m := make(map[string]string) //初始化map
m["stu01"]="stu01"
mapchan <- m //往channel里面添加数据
}
创建struct,往channel里面添加数据
package main
type student struct{
name string
}
func main(){
var stuchan chan student
stuchan = make(chan student,10)
stu:=student{name:"stu01"}
stuchan <- stu
}
指针形式添加到channel
package main
type student struct{
name string
}
func main(){
var stuchan chan *student
stuchan = make(chan *student,10)
stu:=student{name:"stu01"}
stuchan <- &stu
}
channel超时处理
利用select来处理chan超时
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
for { select { case v := <-chan1: fmt.Println(v) case v := <-chan2: fmt.Println(v) default: time.Sleep(time.Second) fmt.Println("timeout...") } }
time.After()定时器来做处理。
在time.After()计时器触发之前,底层计时器不会被垃圾收集器回收。