golang基础小记(22)——并发之goroutine:使用方式、sync.WaitGroup

goroutine

Go语言的并发通过goroutine实现,其概念类似于线程,属于用户态的线程,我们可以创建很多个goroutine并发工作。goroutine是由Go的运行时(runtime)来调度和管理的。

使用方式

启动goroutine只需要在调用的函数前加上go关键字,函数可以是普通函数也可以是匿名函数。
在程序启动时,Go程序会为main()函数创建一个默认的goroutine。它会在main()函数返回的时候结束,此时所有在main()函数中启动的goroutine不管有没有运行完都会一同结束。
如下例:

func f1() {
	fmt.Println("我是f1")
}

func main() {
	go f1()
	fmt.Println("我是main")
}

输出:

我是main

可以发现,函数f1并没有打印结果,这是因为goroutine启动需要一定的时间,而例子中的main()函数早就结束了,在其中启动的goroutine也随之结束。
再看下例:

func f1() {
	fmt.Println("我是f1")
}

func main() {
	go f1()
	fmt.Println("我是main")
	time.Sleep(time.Second)
}

输出:

我是main
我是f1

我们让main()函数简单的睡眠1秒钟,让goroutine有时间执行完。因为goroutine启动需要时间,所以这里"我是main"先输出。

启动多个goroutine

当我们启动多个goroutine时,我们难以确定要让main()函数睡眠多久,这时我们可以使用sync.WaitGroup来实现goroutine的同步。

sync.WaitGroup介绍

WaitGroup 对象内部有一个计数器,最初从0开始,它有三个方法:Add(), Done(), Wait() 用来控制计数器的数量。Add(n) 每次让计数器+nn不能让计数器为负,否则会引发panicDone() 每次让计数器-1wait() 会阻塞代码的运行,直到计数器的值为0
WaitGroup 对象是结构体类型,传参时需要使用地址,否则进程会死锁。

示例

func f(i int, wg *sync.WaitGroup) {
	defer wg.Done()
	fmt.Printf("我是f%d\n", i)
}

func main() {
	wg := sync.WaitGroup{}
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go f(i, &wg)
	}
	fmt.Println("我是main")
	wg.Wait()
}

输出:

我是f8
我是f3
我是f9
我是f5
我是f6
我是f7
我是f1
我是f0
我是f2
我是main
我是f4

每次的输出顺序都可能不同,因为并发执行时goroutine的调度是随机的。

设置程序占用的最大逻辑核心数

Go语言中可以通过runtime.GOMAXPROCS()函数设置当前程序并发时占用的CPU逻辑核心数,Go1.5版本后默认为当前机器的CPU逻辑核心数。
使用方式:

runtime.GOMAXPROCS(4) // 将程序可占用的最大核心数设置为4个,最多4个任务并行

通过runtime.NumCPU()函数可以获取当前机器的CPU逻辑核心数。

参考文献

参考1:一些概念:goroutine与线程的关系
参考2:关于sync.WaitGroup的用法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值