MST

星途 面试题库

面试题:Go协程并发中的资源竞争问题

假设你有一个Go程序,多个Go协程同时访问和修改同一个共享变量。请描述可能出现的资源竞争问题,如何使用Go语言提供的工具(如sync包)来检测和解决这些问题?给出具体的代码示例说明。
46.8万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

资源竞争问题描述

当多个Go协程同时访问和修改同一个共享变量时,可能会出现资源竞争问题。这是因为Go协程是并发执行的,多个协程对共享变量的读写操作可能会相互干扰,导致程序出现不可预测的结果。例如,一个协程正在读取共享变量的值,同时另一个协程对其进行修改,这可能会导致读取到的值不准确。

使用Go语言工具检测资源竞争问题

Go语言提供了内置的竞态检测器(race detector),可以通过在编译和运行程序时添加 -race 标志来启用。例如:

go run -race main.go

或者编译时:

go build -race -o myprogram main.go
./myprogram

使用Go语言工具解决资源竞争问题

可以使用 sync 包中的工具来解决资源竞争问题。常用的有 sync.Mutex(互斥锁),它可以保证在同一时间只有一个协程能够访问共享变量。

代码示例

package main

import (
    "fmt"
    "sync"
)

var (
    counter int
    mu      sync.Mutex
)

func increment(wg *sync.WaitGroup) {
    defer wg.Done()
    mu.Lock()
    counter++
    mu.Unlock()
}

func main() {
    var wg sync.WaitGroup
    numRoutines := 1000

    for i := 0; i < numRoutines; i++ {
        wg.Add(1)
        go increment(&wg)
    }

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

在上述代码中:

  1. 定义了一个共享变量 counter 和一个互斥锁 mu
  2. increment 函数在修改 counter 之前先获取互斥锁 mu,修改完成后释放锁,这样就保证了同一时间只有一个协程能修改 counter
  3. main 函数中,启动1000个协程并发调用 increment 函数,最后等待所有协程完成并打印 counter 的最终值。通过这种方式,避免了资源竞争问题。