MST

星途 面试题库

面试题:Go chan并发读写的资源竞争优化

假设有多个goroutine并发向同一个channel写入数据,同时有另外多个goroutine从该channel读取数据,可能会出现资源竞争导致数据不一致的情况。请设计一个方案,在保证高性能的同时,有效避免这种资源竞争问题,并说明你的设计思路和关键代码实现。
22.9万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

设计思路

使用Go语言的sync.Mutex来保护对共享资源(这里即向channel写入数据的操作)的访问。在向channel写入数据前加锁,写入完成后解锁,这样同一时间只有一个goroutine能执行写入操作,避免资源竞争。对于读取操作,由于Go语言的channel本身是线程安全的,所以无需额外处理。

关键代码实现

package main

import (
    "fmt"
    "sync"
)

var (
    mu sync.Mutex
    ch = make(chan int)
)

func writer(id int, wg *sync.WaitGroup, num int) {
    defer wg.Done()
    mu.Lock()
    ch <- num * id
    mu.Unlock()
}

func reader(wg *sync.WaitGroup) {
    defer wg.Done()
    for val := range ch {
        fmt.Println("Read:", val)
    }
}

func main() {
    var wg sync.WaitGroup
    numWriters := 5
    numReaders := 3

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

    for i := 1; i <= numWriters; i++ {
        wg.Add(1)
        go writer(i, &wg, 10)
    }

    go func() {
        wg.Wait()
        close(ch)
    }()

    wg.Wait()
}

在上述代码中:

  1. 定义了一个sync.Mutex类型的mu和一个int类型的channel ch
  2. writer函数负责向ch写入数据,在写入前调用mu.Lock()加锁,写入后调用mu.Unlock()解锁。
  3. reader函数从ch中读取数据,由于channel本身线程安全,所以无需额外同步操作。
  4. main函数中,启动多个writerreader goroutine,等待所有writer完成后关闭chreaderch关闭后会结束循环。