面试题答案
一键面试实现思路
- 定义缓冲区:使用切片或通道来作为数据的暂存区。
- 生产者逻辑:生成数据并将其放入缓冲区。如果缓冲区已满,生产者需要等待,直到缓冲区有空间。
- 消费者逻辑:从缓冲区取出数据并处理。如果缓冲区为空,消费者需要等待,直到缓冲区有数据。
- 使用
sync.Cond
:用于协调生产者和消费者的等待和唤醒操作。sync.Cond
依赖于一个sync.Mutex
来保护共享资源(即缓冲区)。
关键代码片段
package main
import (
"fmt"
"sync"
"time"
)
type Buffer struct {
data []int
capacity int
mutex sync.Mutex
cond *sync.Cond
}
func NewBuffer(capacity int) *Buffer {
b := &Buffer{
data: make([]int, 0, capacity),
capacity: capacity,
}
b.cond = sync.NewCond(&b.mutex)
return b
}
// 生产者
func Producer(buffer *Buffer, id int) {
for {
buffer.mutex.Lock()
for len(buffer.data) == buffer.capacity {
buffer.cond.Wait()
}
num := id * 10 + len(buffer.data)
buffer.data = append(buffer.data, num)
fmt.Printf("Producer %d produced %d\n", id, num)
buffer.cond.Broadcast()
buffer.mutex.Unlock()
time.Sleep(time.Millisecond * 500)
}
}
// 消费者
func Consumer(buffer *Buffer, id int) {
for {
buffer.mutex.Lock()
for len(buffer.data) == 0 {
buffer.cond.Wait()
}
num := buffer.data[0]
buffer.data = buffer.data[1:]
fmt.Printf("Consumer %d consumed %d\n", id, num)
buffer.cond.Broadcast()
buffer.mutex.Unlock()
time.Sleep(time.Millisecond * 1000)
}
}
在 main
函数中可以这样使用:
func main() {
buffer := NewBuffer(5)
go Producer(buffer, 1)
go Producer(buffer, 2)
go Consumer(buffer, 1)
go Consumer(buffer, 2)
select {}
}