MST

星途 面试题库

面试题:如何在并发环境下合理利用Go无缓冲通道避免死锁

假设你正在开发一个高并发的Go程序,需要使用无缓冲通道进行数据传递,同时要确保不会出现死锁。请阐述你的设计思路,并给出关键代码片段。
46.4万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 通道使用原则:无缓冲通道在发送和接收操作上具有同步性,发送操作会阻塞直到有接收者准备好接收数据,反之亦然。因此,在使用无缓冲通道时,要确保发送和接收操作能够合理匹配,避免单方面的永久阻塞。
  2. 并发协程管理:启动多个协程进行数据处理时,要明确每个协程的职责,尤其是哪些协程负责发送数据到通道,哪些负责从通道接收数据。同时,要注意协程的生命周期管理,避免协程泄露。
  3. 数据流动控制:通过适当的同步机制,如WaitGroup,来协调各个协程的执行,确保所有协程在程序结束前都能正常完成任务。

关键代码片段

package main

import (
    "fmt"
    "sync"
)

func sender(ch chan int, wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < 5; i++ {
        ch <- i
        fmt.Printf("Sent: %d\n", i)
    }
    close(ch)
}

func receiver(ch chan int, wg *sync.WaitGroup) {
    defer wg.Done()
    for val := range ch {
        fmt.Printf("Received: %d\n", val)
    }
}

func main() {
    var wg sync.WaitGroup
    ch := make(chan int)

    wg.Add(2)
    go sender(ch, &wg)
    go receiver(ch, &wg)

    wg.Wait()
}

在上述代码中:

  • sender 协程负责向无缓冲通道 ch 发送数据,发送完成后关闭通道。
  • receiver 协程使用 for... range 循环从通道接收数据,直到通道关闭。
  • WaitGroup 用于等待两个协程完成任务,避免程序提前退出。这样可以有效避免死锁情况的发生。