MST

星途 面试题库

面试题:Go函数的并发安全与资源管理

在Go函数编程中,当多个协程并发调用同一个函数,且该函数涉及共享资源的读写操作时,如何保证并发安全?请详细阐述实现思路,并给出相应的代码示例。
43.3万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 实现思路
    • 互斥锁(Mutex):使用sync.Mutex来保护共享资源。在访问共享资源前加锁,访问完成后解锁。这样同一时间只有一个协程能访问共享资源,避免数据竞争。
    • 读写锁(RWMutex):如果对共享资源的读操作远多于写操作,可以使用sync.RWMutex。读操作时可以多个协程同时进行(加读锁),写操作时则需要独占(加写锁),以保证数据一致性。
  2. 代码示例(使用互斥锁)
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. 代码示例(使用读写锁,假设读多写少场景)
package main

import (
    "fmt"
    "sync"
    "time"
)

var (
    data  int
    rwmu  sync.RWMutex
)

func read(wg *sync.WaitGroup) {
    defer wg.Done()
    rwmu.RLock()
    fmt.Printf("Read value: %d\n", data)
    rwmu.RUnlock()
}

func write(wg *sync.WaitGroup) {
    defer wg.Done()
    rwmu.Lock()
    data++
    fmt.Printf("Write new value: %d\n", data)
    rwmu.Unlock()
}

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go read(&wg)
    }
    for i := 0; i < 2; i++ {
        wg.Add(1)
        go write(&wg)
    }
    time.Sleep(2 * time.Second)
    wg.Wait()
}