MST

星途 面试题库

面试题:Go闭包在并发编程中如何实现数据共享

在Go并发编程场景下,阐述如何利用闭包实现多个goroutine之间的数据共享,并举例说明实现过程中可能遇到的问题及解决方案。
18.0万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

利用闭包实现多个goroutine之间的数据共享

在Go语言中,可以通过闭包来捕获外部变量,使得多个goroutine可以访问和修改这些共享数据。例如:

package main

import (
    "fmt"
)

func main() {
    sharedData := 0
    var routines []func()
    for i := 0; i < 5; i++ {
       routine := func() {
          sharedData++
          fmt.Println("goroutine ", i, " incremented sharedData to ", sharedData)
       }
       routines = append(routines, routine)
    }
    for _, routine := range routines {
       go routine()
    }
    // 为了让所有goroutine有时间执行,这里简单睡眠一下
    select {}
}

在上述代码中,sharedData 是外部变量,闭包函数 routine 捕获了 sharedData,使得每个goroutine都可以访问和修改这个共享数据。

实现过程中可能遇到的问题

  1. 数据竞争问题:当多个goroutine同时访问和修改共享数据时,会发生数据竞争。在上述代码中,如果运行,会发现输出的结果可能不是预期的顺序,并且最终的 sharedData 值可能不正确。这是因为多个goroutine同时对 sharedData 进行自增操作,没有同步机制,导致数据竞争。

解决方案

  1. 使用互斥锁(Mutex):通过在访问共享数据前加锁,访问完后解锁,保证同一时间只有一个goroutine可以访问共享数据。
package main

import (
    "fmt"
    "sync"
)

func main() {
    var mu sync.Mutex
    sharedData := 0
    var routines []func()
    for i := 0; i < 5; i++ {
       routine := func() {
          mu.Lock()
          sharedData++
          fmt.Println("goroutine ", i, " incremented sharedData to ", sharedData)
          mu.Unlock()
       }
       routines = append(routines, routine)
    }
    for _, routine := range routines {
       go routine()
    }
    // 为了让所有goroutine有时间执行,这里简单睡眠一下
    select {}
}
  1. 使用通道(Channel):可以将对共享数据的操作通过通道发送给一个专门处理这些操作的goroutine,由这个goroutine来保证数据的一致性。
package main

import (
    "fmt"
)

func main() {
    sharedData := 0
    operationCh := make(chan func())
    var wg sync.WaitGroup
    wg.Add(5)

    go func() {
       for op := range operationCh {
          op()
          wg.Done()
       }
    }()

    for i := 0; i < 5; i++ {
       operationCh <- func() {
          sharedData++
          fmt.Println("goroutine ", i, " incremented sharedData to ", sharedData)
       }
    }
    close(operationCh)
    wg.Wait()
}

通过上述方式,可以有效地解决在使用闭包实现多个goroutine之间数据共享时遇到的数据竞争问题。