面试题答案
一键面试数据竞争问题
在多协程并发环境下,多个协程向同一个通道写入数据并关闭通道时,可能出现以下数据竞争问题:
- 重复关闭通道:多个协程可能都尝试关闭通道,这会导致运行时恐慌(
panic: close of closed channel
)。 - 未完全写入就关闭:某个协程可能在其他协程还未完成写入数据时就关闭了通道,导致部分数据丢失。
同步机制及代码示例
为避免这些问题,可以使用sync.WaitGroup
来同步协程。sync.WaitGroup
用于等待一组协程完成其工作。
以下是Go语言的代码示例:
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
ch := make(chan int)
// 模拟多个协程写入数据
for i := 0; i < 3; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
ch <- id * 10
}(i)
}
// 独立的协程用于关闭通道
go func() {
wg.Wait()
close(ch)
}()
// 主协程读取数据
for val := range ch {
fmt.Println("Received:", val)
}
}
在上述代码中:
sync.WaitGroup
用于等待所有写入协程完成写入操作。每个写入协程开始前调用wg.Add(1)
,结束时调用wg.Done()
。- 一个独立的协程等待所有写入协程完成(
wg.Wait()
)后,关闭通道(close(ch)
),这样可以避免重复关闭通道和未完全写入就关闭通道的问题。 - 主协程通过
for... range
循环从通道读取数据,直到通道关闭。