用syc.WaitGroup来等待go协程执行完毕, 顺便看看协程并发数的控制方法

        看程序:

package main

import (
	"fmt"
	"time"
)

func print(i int) {
	time.Sleep(1e9)
	fmt.Println(i)
}

func main() {
	for i := 0; i < 10; i++ {
		go func(n int) {
			print(n)
		}(i)
	}
}

         结果没有任何输出,因为主协程很快退出了。

         等待一下,变为:

package main

import (
	"fmt"
	"time"
)

func print(i int) {
	time.Sleep(1e9)
	fmt.Println(i)
}

func main() {
	for i := 0; i < 10; i++ {
		go func(n int) {
			print(n)
		}(i)
	}

	for {}
}

         结果:

7
9
3
4
5
8
0
6
1
2

 

       这种等待太傻了, 改为:

package main

import (
	"fmt"
	"sync"
	"time"
)

func print(i int) {
	time.Sleep(1e9)
	fmt.Println(i)
}

func main() {
	var wg sync.WaitGroup

	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func(n int) {
			defer wg.Add(-1)  // same: defer wg.Done()
			print(n)
		}(i)
	}

	wg.Wait() 
}


         结果:

8
1
5
0
9
4
7
2
6
3

       分析一下wg.Wait执行等待操作, 直到wg的计数变为0才返回。 在上面例子中,Add(1)了10次, 然后Add(-1)了10次,刚好。 我们把程序变一下:

package main

import (
	"fmt"
	"sync"
	"time"
)

func print(i int) {
	time.Sleep(1e9)
	fmt.Println(i)
}

func main() {
	var wg sync.WaitGroup

	wg.Add(11)

	for i := 0; i < 10; i++ {
		go func(n int) {
			defer wg.Add(-1)  // same: defer wg.Done()
			print(n)
		}(i)
	}

	wg.Wait() 
}

        可以看到,计数达到11次,但只有10次的add(-1), 显然wg.Wait永远无法退出,提示:fatal error: all goroutines are asleep - deadlock!

        再看:

package main

import (
	"fmt"
	"sync"
	"time"
)

func print(i int) {
	time.Sleep(1e9)
	fmt.Println(i)
}

func main() {
	var wg sync.WaitGroup

	wg.Add(5)

	for i := 0; i < 10; i++ {
		go func(n int) {
			defer wg.Add(-1)  // same: defer wg.Done()
			print(n)
		}(i)
	}

	wg.Wait() 
}


        结果出错,提示信息:

panic: sync: WaitGroup is reused before previous Wait has returned

panic: sync: negative WaitGroup counter

        看到没, negative counter了。

 

        最后,来看看协程并发数目的控制。 假设有102个离线任务需要并发执行,难道要开102个协程吗? 来看看怎么控制:

package main

import (
	"fmt"
	"sync"
	"time"
)

func print(i int) {
	time.Sleep(1e9)
}

func main() {
	var wg sync.WaitGroup
    begin := time.Now().Unix()

    j := 0
	for i := 0; i < 102; i++ {
		wg.Add(1)

		go func(n int) {
			defer wg.Add(-1) 
			print(n)
		}(i)

		j++
		if j == 10 {
		   wg.Wait()
		   j = 0
		}
	}

	wg.Wait() 

	end := time.Now().Unix()

	fmt.Println(end - begin)
}

         分析下结果, 不难得知, 结果为11. 运行了一下, OK. 

         另外,要注意,即使写连续写多个wg.Wait,也没有问题。

         不多说。

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值