书接上文:go并发打印数字
type5:
func main() {
// 猜猜会打印什么,为啥?
// runtime.GOMAXPROCS(1)
wg := &sync.WaitGroup{}
wg.Add(10)
for i := 0; i < 10; i++ {
go func() {
defer wg.Done()
// 1.18以后闭包的循环变量不在共享同一个地址,已解决这个bug
print(i)
}()
}
wg.Wait()
}
type6:
type worker struct {
ch chan int
done func()
}
func generator(done func()) worker {
w := worker{
ch: make(chan int),
done: done,
}
go func() {
for n := range w.ch {
print(n)
done()
}
}()
return w
}
func main() {
// 用waitGroup实现并发控制
var (
n = 10
wg sync.WaitGroup
ws = make([]worker, n)
)
for i := 0; i < n; i++ {
ws[i] = generator(func() {
wg.Done()
})
}
wg.Add(n)
for i := 0; i < 10; i++ {
ws[i].ch <- i
}
wg.Wait()
}
type7:(解决type3的顺序打印)
话外音:顺序打印的原因是,发送i(sendq存了一个goroutine)后立马被打印(读队列发现写队列有阻塞goroutine优势无缓冲channel立马copy值到读goroutine)
func worker(ch <-chan int, wg *sync.WaitGroup) {
defer wg.Done()
for {
select {
case n := <-ch:
print(n)
case <-time.NewTicker(time.Second).C:
return
}
}
}
func main() {
wg := new(sync.WaitGroup)
ch := make(chan int)
wg.Add(1)
// 开一个goroutine收值
go worker(ch, wg)
for i := 0; i < 10; i++ {
go func(i int) {
ch <- i
}(i)
}
wg.Wait()
}
type8:
func worker(ch <-chan int, wg *sync.WaitGroup) {
defer wg.Done()
for {
select {
case n := <-ch:
print(n)
case <-time.NewTicker(time.Second).C:
return
}
}
}
func main() {
wg := new(sync.WaitGroup)
ch := make(chan int)
wg.Add(10)
for i := 0; i < 10; i++ {
//开10个gouroutine收值
go worker(ch, wg)
go func(i int) {
ch <- i
}(i)
}
wg.Wait()
}
type9:
type worker struct {
ch chan int
done func()
}
func generator(done func()) worker {
w := worker{
ch: make(chan int),
done: done,
}
go func() {
for n := range w.ch {
print(n)
done()
}
}()
return w
}
func main() {
var (
n = 10
// channel实现并发控制,struct{}占用0字节的内存空间(指向8字节zerobase全局变量)
done = make(chan struct{})
ws = make([]worker, n)
)
for i := 0; i < n; i++ {
ws[i] = generator(func() {
done <- struct{}{}
})
}
for i := 0; i < 10; i++ {
ws[i].ch <- i
}
for i := 0; i < 10; i++ {
<-done
}
}
type10:下回分解...