MST
星途 面试题库

面试题:Go匿名函数在并发编程中的应用

在Go语言的并发编程场景下,使用匿名函数配合goroutine实现一个简单的生产者 - 消费者模型。请详细说明如何避免数据竞争和死锁问题。
36.4万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

生产者 - 消费者模型实现

package main

import (
    "fmt"
)

func main() {
    ch := make(chan int)

    // 生产者
    go func() {
        for i := 0; i < 5; i++ {
            ch <- i
        }
        close(ch)
    }()

    // 消费者
    go func() {
        for val := range ch {
            fmt.Println("Consumed:", val)
        }
    }()

    // 防止主函数退出
    select {}
}

避免数据竞争

  1. 使用通道(Channel):在上述代码中,通过使用 chan 来传递数据。通道是类型化的管道,通过它可以在多个 goroutine 之间进行安全的数据传递。由于通道本身是线程安全的,通过通道传递数据就避免了对共享数据的直接访问,从而避免了数据竞争。
  2. 避免共享可变数据:尽量减少不同 goroutine 之间对共享可变数据的操作。在生产者 - 消费者模型中,数据通过通道进行传递,而不是多个 goroutine 直接读写共享变量。

避免死锁

  1. 正确关闭通道:在生产者完成数据生产后,要及时关闭通道。如上述代码中,生产者在生产完数据后调用 close(ch)。消费者通过 for... range 循环从通道读取数据,当通道关闭时,循环会自动结束,避免了消费者因一直等待数据而导致的死锁。
  2. 确保缓冲足够:如果使用带缓冲的通道,要确保缓冲大小足够,防止生产者因通道缓冲区满而阻塞,同时消费者又在等待数据的情况。例如,如果预计生产者会快速生产大量数据,可以适当增大通道的缓冲大小 ch := make(chan int, 10)
  3. 避免循环依赖:在更复杂的并发场景中,要注意避免出现 goroutine 之间相互等待对方释放资源的循环依赖情况,确保各个 goroutine 的执行逻辑不会形成死锁的条件。