【go】goroutine协程

1.进程、线程小知识
进程是程序在os中的一次执行过程。是资源分配和调度的最小单位

线程是程序执行的最小单位,
同一个进程中的多个线程可以并发执行
一个程序至少一个进程,一个进程至少一个线程

2.go主线程(有时直接叫线程/可以理解为传统意义上的进程)
在一个go线程上,可以起多个协程(可以理解为轻量的线程)

3.go协程的特点
·独立的栈空间
·共享程序的堆空间
·用户控制调度
·协程是轻量级的线程

4.协程sample

//主线程(进程)中 开启一个roroutine 每隔1s输出
//主线程也每隔一秒输出 同时执行

func test() {
	for i := 1; i <= 10; i++ {
		fmt.Println("test() hello, world " + strconv.Itoa(i))
		time.Sleep(time.Second)
	}
}

func main(){
	go test() //开启了一个协程
	for i := 1; i <= 10; i++ {
		fmt.Println("main() hello, golang " + strconv.Itoa(i))
		time.Sleep(time.Second)
	}
}

可以理解为主线程运行到go语句 开启一个协程分支独立执行

如果主线程推出了,协程还没有执行完,也会退出

5.主线程的物理的,直接作用在cpu上的。是重量级的,非常耗费cpu资源
协程是主线程开启的,是逻辑态,对资源消耗相对小

golang可以轻松开启上万个协程,并发优势巨大

6.MPG模式

M: os的主线程(物理线程)
P:协程执行所需要的上下文
G:协程

7.golang
查询cpu数量,设置使用多少个cpu

	cpuNum := runtime.NumCPU()
	fmt.Println("cpuNum =", cpuNum)
	//可以自己设置使用多少个CPU
	runtime.GOMAXPROCS(cpuNum - 1)
	fmt.Println("ok")

1.8以后默认程序运行在多个核上 不用设置

8.并发势必会出现资源冲突的问题
如何知道是否出现资源冲突

go build -race test.go
test.go

9.互斥锁
只适用于低水平的并发程序

//计算1-200的各个数的阶乘 并放到map
//用goroutine完成 启动多个协程 将结果放入map中
//map声明为全局的
//避免出现concurrent map writes
var (
	mp = make(map[int]int, 10)
	//全局的互斥锁
	lock sync.Mutex
)

func test(n int) {
	res := 1
	for i := 1; i <= n; i++{
		res *= i
	}
	lock.Lock()
	mp[n] = res
	lock.Unlock()
}

func main(){
	for i := 1; i <= 20; i++ {
		go test(i)
	}

	//要休眠 不然主线程直接跑完了
	time.Sleep(time.Second * 5)
	//读也要加锁 否则还会冲突
	lock.Lock()
	for i, v := range mp{
		fmt.Printf("mp[%v] = %v\n", i, v)
	}
	lock.Unlock()
}

用全局变量的互斥锁和主线程睡眠 解决了问题
但是很蠢
管道方法见下一篇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>