MST

星途 面试题库

面试题:Go函数异步调用中的资源竞争处理

编写一个Go程序,其中包含多个异步函数同时对共享资源进行读写操作。在异步调用过程中,通过合适的同步机制(如互斥锁、读写锁等)来避免资源竞争问题,并详细阐述每种同步机制在这种场景下的优缺点。
32.7万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

Go程序示例

package main

import (
    "fmt"
    "sync"
)

// 定义共享资源
var sharedData int
var mu sync.Mutex
var rwMutex sync.RWMutex

// 使用互斥锁进行写操作的函数
func writeWithMutex(wg *sync.WaitGroup) {
    defer wg.Done()
    mu.Lock()
    sharedData++
    mu.Unlock()
}

// 使用读写锁进行读操作的函数
func readWithRWMutex(wg *sync.WaitGroup) {
    defer wg.Done()
    rwMutex.RLock()
    fmt.Printf("Read data: %d\n", sharedData)
    rwMutex.RUnlock()
}

func main() {
    var wg sync.WaitGroup

    // 启动多个写操作
    for i := 0; i < 3; i++ {
        wg.Add(1)
        go writeWithMutex(&wg)
    }

    // 启动多个读操作
    for i := 0; i < 3; i++ {
        wg.Add(1)
        go readWithRWMutex(&wg)
    }

    wg.Wait()
}

同步机制优缺点分析

  1. 互斥锁(Mutex)
    • 优点
      • 简单易用,适用于读写操作都需要独占访问共享资源的场景。无论是读操作还是写操作,都能保证同一时间只有一个goroutine可以访问共享资源,有效避免资源竞争。
      • 可以保证数据的一致性,因为每次只有一个goroutine能修改共享资源。
    • 缺点
      • 性能瓶颈明显,在读操作频繁的场景下,由于每次读操作都需要获取互斥锁,其他读操作也会被阻塞,导致并发性能降低。因为互斥锁不区分读和写,只要有一个goroutine获取了锁,其他所有goroutine无论是读还是写都得等待。
  2. 读写锁(RWMutex)
    • 优点
      • 在读多写少的场景下性能优越。多个读操作可以同时进行,因为读操作不会修改共享资源,所以不会产生数据竞争。只有写操作需要独占锁,这样可以大大提高并发读的效率。
      • 适用于大部分操作是读取共享资源,而写操作相对较少的应用场景,比如配置文件的读取和偶尔的更新。
    • 缺点
      • 实现相对复杂,相比于互斥锁,需要更多的代码逻辑来管理读锁和写锁的获取与释放。
      • 在写操作时,所有读操作和其他写操作都被阻塞,所以如果写操作频繁,可能会导致读操作长时间等待,降低系统整体的响应性。同时,如果写操作持有写锁时间过长,会影响读操作的并发性能。