Go基础知识复习之goroutine

上一篇我们已经知道go语言的strconv包

今天介绍goroutine


在go里面 每一个并发执行的活动成为goroutine
goroutine可以认为是轻量级的线程,与创建线程相比,创建成本和开销都很小
当一个程序启动的时候,只有一个goroutine来调用main函数,称它为主goroutine,
新的goroutine通过go语句进行创建。

在函数的使用前面增加关键字 go 就可以创建一个并发运行的新goroutine。
示例:

package main
import(
	"fmt"
)
func hello(){
	fmt.Println("this is hello")
}
func main(){
	fmt.Println("this is main")
	//如果只是调用函数 那么执行顺序是自上而下的 因为hello的调用是存在于main的goroutine中
	//加上 关键字go 看看会发生什么情况?
	go hello()
	
}

通过上述的例子,可以看到,调用hello函数之后 并不会出现结果
为什么呢?
因为此时执行hello函数的goroutine是不属于main函数的 ,main函数执行this is main的输出之后,就结束了
那么如何让hello函数成功调用并输出呢


package main
import(
	"fmt"
	"time"
)
func hello(){
	fmt.Println("this is hello")
}
func main(){
	fmt.Println("this is main")
	//新建一个goroutine
	go hello()
	//再建一个goroutine
	for i:=1;i<=5;i++{
		go func(i int){
			fmt.Println(i)
		}(i)
	}
	//给main函数设置休眠时间 让负责调用hello函数的goroutine有时间去执行
	time.Sleep(time.Second)
	
}

多个goroutine

上面的写法不够规范严谨,可以通过导入sync包的WaitGroup来完善!
需要用到三个方法

  1. Add() 新增一个goroutine
  2. Done() 减去一个goroutine
  3. Wait() 等待
package main

import(
	"fmt"
	"sync"
	"math/rand"
	"time"
)
//声明结构体   等待组 等待让goroutine去结束  goroutine的结束 意味着 对应的函数 也就结束了
var wg sync.WaitGroup
//示例1:返回随机数的函数
func f(){
	//goroutine进来就消费一个所以是Done  这里需要defer 为什么呢 因为可以保证在函数返回和赋值之间去执行
	defer wg.Done()
	//这里就需要配置时间种子 让每次goroutine执行的时候产生的时间不同
	rand.Seed(time.Now().UnixNano())
	//输出一定数量的随机数
	for i:=0;i<5;i++{
		//返回随机长度的int随机数
		r1:=rand.Int()
		//返回长度为0到10长度的随机数
		r2:=rand.Intn(10)
		fmt.Println(r1,r2)
	}
}
//示例2:传入参数返回本身
func f2(i int){
	defer wg.Done()
	fmt.Println(i)
}
func main(){
	//新增
	wg.Add(1)
	//开启运行goroutine
	go f()
	
	for u:=0;u<10;u++{
		wg.Add(1)
		go f2(u)
	}
	
	//结束了 呈现等待
	wg.Wait()
}

通过上面的示例,在多个goroutine一起执行的情况下,是处于并行的状态去执行,所以每次运行出来的结果都是不一样的。

GMP

先了解:
一个操作系统的线程 对应多个的 goroutine
go程序可以同事使用多个操作系统线程
goroutine 和 OS 线程是 多对多的关系

所谓的GMP,我们在这里拆开:
G表示goroutine
M表示和操作系统映射的关系
P表示调度者队列

模拟把多个goroutine分配给多个操作系统进行执行
package main

import(
	"fmt"
	"runtime"
	"sync"
)

var wg sync.WaitGroup
func a(){
	defer wg.Done()
	for i:=0;i<10;i++{
		fmt.Printf("A:%d \n",i)
	}
}
func b(){
	defer wg.Done()
	for j:=0;j<10;j++{
		fmt.Printf("a:%d \n",j)
	}
}
func main(){
	//输出逻辑核心数
	fmt.Println(runtime.NumCPU())
	runtime.GOMAXPROCS(1)//给一个CPU的逻辑核心数进行处理
	wg.Add(2)
	go a()
	go b()
	wg.Wait()
	
}

关于goroutine的介绍先到这边,可能不太明确是什么,但是先知道有这么个东西,后续的文章会去加固这方面的知识!
未完待续。。。

你可能感兴趣的:(PHP)