面试题答案
一键面试以下是使用Go语言实现该功能的代码示例:
package main
import (
"fmt"
)
func writeToChannel(ch chan int, id int) {
for i := 0; i < 5; i++ {
ch <- id*10 + i
}
close(ch)
}
func readFromChannel(channels []chan int) {
var mergedCh = make(chan int)
defer close(mergedCh)
for _, ch := range channels {
go func(c chan int) {
for val := range c {
mergedCh <- val
}
}(ch)
}
for val := range mergedCh {
fmt.Println("Processed:", val)
}
}
func main() {
var numTasks = 3
var channels = make([]chan int, numTasks)
for i := 0; i < numTasks; i++ {
channels[i] = make(chan int)
go writeToChannel(channels[i], i)
}
readFromChannel(channels)
}
数据竞争问题处理
- 使用Channel进行通信:在Go语言中,通过Channel进行通信是线程安全的。每个任务向自己的Channel写入数据,然后通过合并多个Channel的方式(如上述代码中
readFromChannel
函数),将数据传递到一个统一的处理流程,避免了直接共享内存带来的数据竞争。 - 关闭Channel:在写入完成后,及时关闭Channel,这样读取端可以通过
for... range
循环优雅地结束读取,避免出现死锁或未定义行为。
数据一致性和同步性保证
- 同步:通过Channel进行同步,写入端向Channel写入数据,读取端从Channel读取数据,这种生产者 - 消费者模型天然保证了一定程度的同步。写入操作和读取操作是顺序执行的,不会出现同时读写同一数据的情况。
- 一致性:由于每个任务都有自己独立的写入Channel,并且通过合并Channel来统一读取,所以不会出现不同任务同时修改同一数据导致数据不一致的问题。同时,关闭Channel的操作也保证了数据完整性,读取端可以完整地获取所有写入的数据。