Created
July 2, 2024 10:05
-
-
Save noname007/6fd0a23920fa115618dbef2504511727 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Golang 面试题 (4) N个协程交替打印1-100 | |
启动N个协程,共用一个外部变量计数器,计数器范围是1到100 | |
开启N个有缓冲chan,chans[i]塞入数据代表协程i可以进行打印了,打印的数字就是计数器的数 | |
协程i一直阻塞,直到chan[i]通道有数据可以拉,才打印 |
Author
noname007
commented
Jul 2, 2024
copy https://www.cnblogs.com/yinbiao/p/16142008.html
func main() {
gorutinenum := 5
var chanslice []chan int
exitchan := make(chan int)
for i := 0; i < gorutinenum; i++ {
chanslice = append(chanslice, make(chan int, 1))
}
res := 1
j := 0
for i := 0; i < gorutinenum; i ++ {
go func(i int) {
for {
<-chanslice[i]
if res > 100 {
exitchan <- 1
break
}
fmt.Println(fmt.Sprintf("gorutine%v:%v", i, res))
res ++
if j == gorutinenum-1 {
j = 0
}else {
j ++
}
chanslice[j] <- 1
}
}(i)
}
chanslice[0] <- 1
select {
case <-exitchan:
fmt.Println("end")
}
}
与上面的代码一样,存在协程资源泄露问题,没有做回收
package main
import (
"fmt"
"sync"
)
//N个协程交替打印数字,到达一个数值后终止
//
//解法:
//启动N个协程,共用一个外部变量计数器,计数器范围是1到100
//开启N个无缓冲chan,chans[i]塞入数据代表协程i可以进行打印了,打印的数字就是计数器的数
//协程i一直阻塞,直到chan[i]通道有数据可以拉,才打印
//
var counter = 0
func DoJob(chans []chan int64) {
chanLen := len(chans)
quitCh := make(chan int)
wg := sync.WaitGroup{}
for i := 0; i < chanLen; i++ {
go func(idx int) {
wg.Add(1)
defer wg.Done()
for {
<-chans[idx]
if counter > 100 {
quitCh <- 1
break
}
fmt.Printf("goroutine-num:%d %d\n", idx, counter)
counter += 1
chans[(idx+1)%chanLen] <- 1
}
}(i)
}
chans[0] <- 1
<-quitCh
wg.Wait()
}
func main() {
//chanNum := 1 //panic
chanNum := 10
chans := make([]chan int64, chanNum)
for i := 0; i < (chanNum); i++ {
chans[i] = make(chan int64)
}
DoJob(chans)
}
package main
import (
"fmt"
"sync"
)
//N个协程交替打印数字,到达一个数值后终止
//
//解法:
//启动N个协程,共用一个外部变量计数器,计数器范围是1到100
//开启N个无缓冲chan,chans[i]塞入数据代表协程i可以进行打印了,打印的数字就是计数器的数
//协程i一直阻塞,直到chan[i]通道有数据可以拉,才打印
//
var counter = 0
const CounterMaxValue = 100
func DoJob(GoRoutineNum int) {
//用于控制业务逻辑
sigChannel := make([]chan struct{}, GoRoutineNum)
//用于控制协成是否终结
quitSigChannel := make([]chan struct{}, GoRoutineNum)
for i := 0; i < (GoRoutineNum); i++ {
sigChannel[i] = make(chan struct{})
quitSigChannel[i] = make(chan struct{})
}
mainRoutine := make(chan struct{})
wg := sync.WaitGroup{}
for i := 0; i < GoRoutineNum; i++ {
wg.Add(1)
go func(idx int) {
defer wg.Done()
//FOR:
for {
select {
case <-quitSigChannel[idx]:
//break FOR
goto END
case <-sigChannel[idx]:
fmt.Printf("goroutine-num:%d %d\n", idx, counter)
counter += 1
mainRoutine <- struct{}{}
}
}
END:
fmt.Printf("goroutine-num:%d end\n", idx)
}(i)
}
wg.Add(1)
go func() {
wg.Done()
for i := 0; i < CounterMaxValue; i++ {
//<-mainRoutine
sigChannel[i%GoRoutineNum] <- struct{}{}
<-mainRoutine
}
////使最后一个任务处理协成,进入信号等待状态
//<-mainRoutine
for i := 0; i < GoRoutineNum; i++ {
quitSigChannel[i] <- struct{}{}
}
}()
//mainRoutine <- struct{}{}
wg.Wait()
}
func main() {
DoJob(10)
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment