MST

星途 面试题库

面试题:如何使用sync包实现Go语言切片的并发安全

给定一个Go语言切片,要求通过使用sync包中的相关工具(如Mutex、WaitGroup等),编写代码实现对该切片的并发安全读写操作,并阐述代码实现原理。
42.3万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

代码实现

package main

import (
    "fmt"
    "sync"
)

var (
    dataSlice []int
    mu        sync.Mutex
    wg        sync.WaitGroup
)

func writeData(num int) {
    defer wg.Done()
    mu.Lock()
    dataSlice = append(dataSlice, num)
    mu.Unlock()
}

func readData() {
    defer wg.Done()
    mu.Lock()
    for _, v := range dataSlice {
        fmt.Println(v)
    }
    mu.Unlock()
}

func main() {
    // 模拟并发写操作
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go writeData(i)
    }

    // 等待所有写操作完成
    wg.Wait()

    // 模拟并发读操作
    wg.Add(1)
    go readData()

    // 等待读操作完成
    wg.Wait()
}

实现原理

  1. Mutex:使用sync.Mutex来保护对dataSlice的读写操作。在写操作writeData和读操作readData中,首先通过mu.Lock()加锁,这样在同一时间只有一个goroutine能够访问dataSlice,防止多个goroutine同时读写导致数据竞争。操作完成后,通过mu.Unlock()解锁,允许其他goroutine进行操作。
  2. WaitGroup:使用sync.WaitGroup来同步goroutine。在启动每个写操作的goroutine前,通过wg.Add(1)增加等待组的计数。在写操作完成后,通过wg.Done()减少计数。在主函数中,使用wg.Wait()等待所有写操作完成后再进行读操作,确保读操作能读取到完整的数据。同样,在启动读操作的goroutine前也增加计数,读操作完成后减少计数,以确保主函数等待所有操作完成后再退出。