MST

星途 面试题库

面试题:Go扇入扇出模式下如何优化资源竞争问题

假设你正在使用Go语言实现一个具有扇入扇出模式的高并发系统,该系统涉及多个协程对共享资源的读写操作,产生了资源竞争。请描述你会采取哪些优化策略来解决这些资源竞争问题,并给出关键代码示例。
47.8万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

优化策略

  1. 互斥锁(Mutex):使用sync.Mutex来保护共享资源,在对共享资源进行读写操作前获取锁,操作完成后释放锁,确保同一时间只有一个协程能访问共享资源。
  2. 读写锁(RWMutex):如果读操作远多于写操作,可以使用sync.RWMutex。读操作时可以多个协程同时进行,写操作时需要独占锁,防止其他读写操作。
  3. 通道(Channel):通过通道在协程间传递数据,避免直接对共享资源进行操作,利用通道的阻塞和同步机制来控制数据流动。
  4. 原子操作:对于简单的共享变量(如计数器),可以使用sync/atomic包中的原子操作函数,它们在硬件层面保证操作的原子性,避免锁的开销。

关键代码示例

  1. 使用互斥锁
package main

import (
    "fmt"
    "sync"
)

var (
    mu    sync.Mutex
    count int
)

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

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go increment(&wg)
    }
    wg.Wait()
    fmt.Println("Final count:", count)
}
  1. 使用读写锁
package main

import (
    "fmt"
    "sync"
)

var (
    rwmu  sync.RWMutex
    value int
)

func read(wg *sync.WaitGroup) {
    defer wg.Done()
    rwmu.RLock()
    fmt.Println("Read value:", value)
    rwmu.RUnlock()
}

func write(wg *sync.WaitGroup) {
    defer wg.Done()
    rwmu.Lock()
    value++
    fmt.Println("Write value:", value)
    rwmu.Unlock()
}

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        if i%2 == 0 {
            wg.Add(1)
            go write(&wg)
        } else {
            wg.Add(1)
            go read(&wg)
        }
    }
    wg.Wait()
}
  1. 使用通道
package main

import (
    "fmt"
    "sync"
)

func producer(ch chan int, wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < 10; i++ {
        ch <- i
    }
    close(ch)
}

func consumer(ch chan int, wg *sync.WaitGroup) {
    defer wg.Done()
    for val := range ch {
        fmt.Println("Consumed:", val)
    }
}

func main() {
    var wg sync.WaitGroup
    ch := make(chan int)
    wg.Add(2)
    go producer(ch, &wg)
    go consumer(ch, &wg)
    wg.Wait()
}
  1. 使用原子操作
package main

import (
    "fmt"
    "sync"
    "sync/atomic"
)

var count int64

func increment(wg *sync.WaitGroup) {
    defer wg.Done()
    atomic.AddInt64(&count, 1)
}

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go increment(&wg)
    }
    wg.Wait()
    fmt.Println("Final count:", atomic.LoadInt64(&count))
}