面试题答案
一键面试设计思路
使用Go语言的sync.Mutex
来保护对共享资源(这里即向channel写入数据的操作)的访问。在向channel写入数据前加锁,写入完成后解锁,这样同一时间只有一个goroutine能执行写入操作,避免资源竞争。对于读取操作,由于Go语言的channel本身是线程安全的,所以无需额外处理。
关键代码实现
package main
import (
"fmt"
"sync"
)
var (
mu sync.Mutex
ch = make(chan int)
)
func writer(id int, wg *sync.WaitGroup, num int) {
defer wg.Done()
mu.Lock()
ch <- num * id
mu.Unlock()
}
func reader(wg *sync.WaitGroup) {
defer wg.Done()
for val := range ch {
fmt.Println("Read:", val)
}
}
func main() {
var wg sync.WaitGroup
numWriters := 5
numReaders := 3
for i := 0; i < numReaders; i++ {
wg.Add(1)
go reader(&wg)
}
for i := 1; i <= numWriters; i++ {
wg.Add(1)
go writer(i, &wg, 10)
}
go func() {
wg.Wait()
close(ch)
}()
wg.Wait()
}
在上述代码中:
- 定义了一个
sync.Mutex
类型的mu
和一个int
类型的channelch
。 writer
函数负责向ch
写入数据,在写入前调用mu.Lock()
加锁,写入后调用mu.Unlock()
解锁。reader
函数从ch
中读取数据,由于channel本身线程安全,所以无需额外同步操作。- 在
main
函数中,启动多个writer
和reader
goroutine,等待所有writer
完成后关闭ch
,reader
在ch
关闭后会结束循环。