MST

星途 面试题库

面试题:Go中使用Channel处理并发任务的同步及数据竞争问题

假设有多个并发任务,每个任务都会向一个共享的Channel写入数据,之后另一个任务从该Channel读取数据并处理。请编写代码实现此过程,并处理可能出现的数据竞争问题,同时阐述如何保证数据的一致性和同步性。
21.7万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

以下是使用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)
}

数据竞争问题处理

  1. 使用Channel进行通信:在Go语言中,通过Channel进行通信是线程安全的。每个任务向自己的Channel写入数据,然后通过合并多个Channel的方式(如上述代码中readFromChannel函数),将数据传递到一个统一的处理流程,避免了直接共享内存带来的数据竞争。
  2. 关闭Channel:在写入完成后,及时关闭Channel,这样读取端可以通过for... range循环优雅地结束读取,避免出现死锁或未定义行为。

数据一致性和同步性保证

  1. 同步:通过Channel进行同步,写入端向Channel写入数据,读取端从Channel读取数据,这种生产者 - 消费者模型天然保证了一定程度的同步。写入操作和读取操作是顺序执行的,不会出现同时读写同一数据的情况。
  2. 一致性:由于每个任务都有自己独立的写入Channel,并且通过合并Channel来统一读取,所以不会出现不同任务同时修改同一数据导致数据不一致的问题。同时,关闭Channel的操作也保证了数据完整性,读取端可以完整地获取所有写入的数据。