前言
开发过程中,如果不限制并发数,如下代码这种,可能直接造成服务器宕机,而且很多结果不会输出
[!TIP|style:flat]
很多结果不会输出,是因为主协程结束时,子协程也会终止掉。
func main() {userCount := math.MaxInt64for i := 0; i < userCount; i++ {go func(i int) {// 做一些各种各样的业务逻辑处理fmt.Printf("go func: %d\n", i)time.Sleep(time.Second)}(i)}}
尝试chan
package mainimport ("fmt""math""time")func out(i int, semaphore chan bool){fmt.Printf("go func: %d\n", i)// 释放通道<- semaphoretime.Sleep(time.Second)}func main() {semaphore := make(chan bool, 2)userCount := math.MaxInt8for i := 0; i < userCount; i++ {// 占用通道semaphore <- truego out(i, semaphore)}}
确实可以2个协程并发,但是和上面结果一样,很多结果不会输出,是因为主协程结束时,子协程也会终止掉。
go func: 1go func: 0go func: 3go func: 4go func: 5go func: 6go func: 7go func: 8
尝试sync
主要使用sync.WaitGroup{}
package mainimport ("fmt""math""sync""time")var wg = sync.WaitGroup{}func out(i int){fmt.Printf("go func: %d\n", i)time.Sleep(time.Second)wg.Done()}func main() {userCount := math.MaxInt8for i := 0; i < userCount; i++ {wg.Add(1)go out(i)}// 等待全部执行完wg.Wait()}
所有结果都显示出来了,也就是说所有子协程都执行完了,但是没有控制并发数量
尝试chan+sync√
从上面2个可以看出,一个可以控制并发数量,另一个可以让所有子协程都执行完,所以结合一下,就能达到我们的目的了
package mainimport ("fmt""math""sync""time")var wg = sync.WaitGroup{}func out(i int, semaphone chan bool){fmt.Printf("go func: %d\n", i)time.Sleep(time.Second)// 释放通道<- semaphonedefer wg.Done()}func main() {semaphone := make(chan bool, 2)userCount := math.MaxInt8for i := 0; i < userCount; i++ {wg.Add(1)// 占用通道semaphone <- truego out(i, semaphone)}// 等待全部执行完wg.Wait()}
结合一下,确实能达到我们想到的效果了!!!就是结果有点乱,一般来说不影响了
go func: 1go func: 0go func: 3go func: 2go func: 4go func: 5go func: 6go func: 7go func: 8go func: 9
信号量Semaphore
和Python中的信号量一样,感觉是结合了chan+sync,确实是一个很好的方案,输出的结果也是按顺序输出的
- https://github.com/EDDYCJY/gsema ``` package main
 
import ( “fmt” “github.com/EDDYCJY/gsema” “math” “time” )
var semaphore = gsema.NewSemaphore(2)
func out(i int){ fmt.Printf(“go func: %d\n”, i) time.Sleep(time.Second) defer semaphore.Done() }
func main() { userCount := math.MaxInt8 for i := 0; i < userCount; i++ { semaphore.Add(1) go out(i) } semaphore.Wait() }
```go func: 0go func: 1go func: 2go func: 3go func: 4go func: 5go func: 6go func: 7go func: 8go func: 9
协程池
这个就是一次性创建所有的协程,然后再根据大小来调用
