MST

星途 面试题库

面试题:Go语言中闭包如何在并发场景下实现数据安全访问

在Go语言中,我们知道闭包可以访问其外层函数的变量。当在并发场景下,多个goroutine同时访问闭包中引用的变量时,可能会引发数据竞争问题。请编写一段Go代码,利用闭包在并发场景下安全地访问和修改一个共享变量,解释你的实现思路,以及为什么这种方式能保证数据安全。
18.5万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
package main

import (
    "fmt"
    "sync"
)

func main() {
    var mu sync.Mutex
    sharedVar := 0

    increment := func() {
        mu.Lock()
        sharedVar++
        mu.Unlock()
    }

    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            increment()
        }()
    }

    wg.Wait()
    fmt.Println("Final value:", sharedVar)
}

实现思路

  1. 定义共享变量和互斥锁:首先定义一个共享变量 sharedVar,并创建一个 sync.Mutex 类型的互斥锁 mu,用于保护对 sharedVar 的访问。
  2. 创建闭包increment 闭包函数封装了对共享变量 sharedVar 的修改操作。在闭包内部,通过调用 mu.Lock() 锁定互斥锁,这样在同一时间只有一个 goroutine 能够进入临界区,对 sharedVar 进行操作。操作完成后,调用 mu.Unlock() 解锁互斥锁,允许其他 goroutine 访问。
  3. 启动多个 goroutine:在 main 函数中,使用 for 循环启动 10 个 goroutine,每个 goroutine 都调用 increment 闭包函数。通过 sync.WaitGroup 等待所有 goroutine 完成操作。

保证数据安全的原因

这种方式能保证数据安全是因为互斥锁的机制。互斥锁只有两种状态:锁定和未锁定。当一个 goroutine 调用 mu.Lock() 时,如果互斥锁处于未锁定状态,它会将其锁定并进入临界区。如果互斥锁已经被锁定,调用 mu.Lock() 的 goroutine 会被阻塞,直到互斥锁被解锁。这样就确保了在任何时刻,只有一个 goroutine 能够访问和修改共享变量 sharedVar,从而避免了数据竞争问题。