60 lines
1.4 KiB
Go
60 lines
1.4 KiB
Go
package main
|
||
|
||
import (
|
||
"fmt"
|
||
"sync"
|
||
"time"
|
||
)
|
||
|
||
var (
|
||
queue []int // 共享队列(生产者-消费者模型)
|
||
cmu sync.Mutex // 保护队列的互斥锁
|
||
cond = sync.NewCond(&cmu) // 基于mu创建条件变量
|
||
cwg sync.WaitGroup
|
||
)
|
||
|
||
// 生产者:向队列添加数据
|
||
func producer(id int) {
|
||
defer cwg.Done()
|
||
for i := 0; i < 3; i++ {
|
||
cmu.Lock()
|
||
data := id*10 + i
|
||
queue = append(queue, data)
|
||
fmt.Printf("生产者%d: 生产数据%d(队列长度%d)\n", id, data, len(queue))
|
||
cmu.Unlock()
|
||
|
||
cond.Signal() // 唤醒一个等待的消费者(通知队列非空)
|
||
time.Sleep(500 * time.Millisecond)
|
||
}
|
||
}
|
||
|
||
// 消费者:等待队列非空后消费数据
|
||
func consumer(id int) {
|
||
defer cwg.Done()
|
||
for i := 0; i < 2; i++ { // 限定消费次数,避免无限等待
|
||
cmu.Lock()
|
||
// 循环等待:避免虚假唤醒(被唤醒时条件可能仍不满足)
|
||
for len(queue) == 0 {
|
||
cond.Wait() // 释放mu并阻塞,被唤醒时重新获取mu
|
||
}
|
||
if len(queue) > 0 { // 确保队列不为空
|
||
data := queue[0]
|
||
queue = queue[1:]
|
||
fmt.Printf("消费者%d: 消费数据%d(剩余长度%d)\n", id, data, len(queue))
|
||
}
|
||
cmu.Unlock()
|
||
}
|
||
}
|
||
|
||
func main() {
|
||
cwg.Add(2) // 2个生产者
|
||
go producer(0)
|
||
go producer(1)
|
||
cwg.Add(3) // 3个消费者
|
||
go consumer(0)
|
||
go consumer(1)
|
||
go consumer(2)
|
||
cwg.Wait()
|
||
fmt.Println("所有生产者和消费者完成")
|
||
}
|