MST

星途 面试题库

面试题:Go函数链式调用在并发场景下的优化

在并发编程场景中,使用Go函数链式调用时可能会遇到资源竞争等问题。请阐述如何在函数链式调用过程中进行优化,以确保并发安全,同时给出具体的优化策略及相关代码示例。
12.2万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

优化策略

  1. 互斥锁(Mutex)
    • 使用Go标准库中的sync.Mutex,在访问共享资源前加锁,访问完成后解锁,防止多个协程同时访问共享资源。
  2. 读写锁(RWMutex)
    • 当读操作远多于写操作时,使用sync.RWMutex。读操作可以并发进行,写操作需要独占锁,这样可以提高读操作的并发性能。
  3. 通道(Channel)
    • 通过通道在协程间传递数据,避免共享数据。通道本身是线程安全的,数据在通道中传递时不需要额外的锁机制。
  4. 原子操作(Atomic)
    • 对于一些简单的共享变量,如计数器等,可以使用sync/atomic包提供的原子操作,这些操作是CPU级别的原子指令,保证操作的原子性,避免竞争。

代码示例

  1. 互斥锁示例
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
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go increment(&wg)
    }
    wg.Wait()
    fmt.Println("Final counter:", counter)
}
  1. 读写锁示例
package main

import (
    "fmt"
    "sync"
)

var (
    data    = make(map[string]int)
    rwMutex sync.RWMutex
)

func read(key string, wg *sync.WaitGroup) {
    defer wg.Done()
    rwMutex.RLock()
    value := data[key]
    rwMutex.RUnlock()
    fmt.Printf("Read %s: %d\n", key, value)
}

func write(key string, val int, wg *sync.WaitGroup) {
    defer wg.Done()
    rwMutex.Lock()
    data[key] = val
    rwMutex.Unlock()
    fmt.Printf("Write %s: %d\n", key, val)
}

func main() {
    var wg sync.WaitGroup
    wg.Add(2)
    go write("test", 1, &wg)
    go read("test", &wg)
    wg.Wait()
}
  1. 通道示例
package main

import (
    "fmt"
    "sync"
)

func producer(ch chan int, wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < 5; 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 counter int64

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

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