package main
import (
"sync"
"fmt"
"time"
)
type numPipe struct {
Mu sync.Mutex
Nums chan int
}
// 向管道写入数据
func push(np numPipe, num int, sleep int) {
np.Mu.Lock()
for i := 0; i < sleep; {
time.Sleep(time.Second)
i += 1
}
np.Nums <- num
np.Mu.Unlock()
}
// 从管道读取数据并打印
func pop(np numPipe) {
defer np.Mu.Unlock()
np.Mu.Lock()
fmt.Println(<-np.Nums)
}
func main() {
np := numPipe{
sync.Mutex{},
make(chan int, 10),
}
var wg sync.WaitGroup
// 模拟随机写入数据
for i := 0; i < 11; {
go push(np, i, i)
i += 1
}
// 告知主协程有子协程需要等待
wg.Add(1)
go func() {
defer wg.Done()
lastPoppedAt := time.Now()
for {
// 如果管道中有数据则读取,避免deadlock
if len(np.Nums) > 0 {
fmt.Println("Popping")
lastPoppedAt = time.Now()
pop(np)
} else {
// 等待时间超过15s则退出
if time.Now().Sub(lastPoppedAt) > (time.Second * 15) {
fmt.Println("Too long to wait")
break
}
time.Sleep(time.Second)
}
}
}()
// 开始等待,主协程还不能结束
wg.Wait()
}
执行结果
$ go run buffer_ch.go
Popping
0
Popping
1
Popping
2
Popping
3
Popping
4
Popping
5
Popping
6
Popping
7
Popping
8
Popping
9
Popping
10
Too long to wait