MST

星途 面试题库

面试题:Go语言闭包在并发读写共享变量时如何确保安全性

假设在Go语言并发程序里,闭包会对某个共享变量进行读写操作,详细说明你会采用哪些方法来保证数据的一致性和安全性,要求给出具体实现代码示例。
28.3万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

在Go语言中,当闭包对共享变量进行读写操作时,可以采用以下几种方法保证数据一致性和安全性:

使用互斥锁(sync.Mutex

互斥锁可以确保在同一时间只有一个goroutine能够访问共享变量。

package main

import (
    "fmt"
    "sync"
)

var (
    mu    sync.Mutex
    count int
)

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            mu.Lock()
            count++
            fmt.Println("Incremented count:", count)
            mu.Unlock()
        }()
    }
    wg.Wait()
}

使用读写锁(sync.RWMutex

如果读操作远多于写操作,可以使用读写锁,允许多个goroutine同时进行读操作,但写操作时会独占锁。

package main

import (
    "fmt"
    "sync"
)

var (
    rwmu  sync.RWMutex
    value int
)

func read(id int) {
    rwmu.RLock()
    fmt.Printf("Reader %d read value: %d\n", id, value)
    rwmu.RUnlock()
}

func write(id int) {
    rwmu.Lock()
    value++
    fmt.Printf("Writer %d incremented value: %d\n", id, value)
    rwmu.Unlock()
}

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            write(id)
        }(i)
    }
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            read(id)
        }(i)
    }
    wg.Wait()
}

使用通道(chan

通过通道来传递对共享变量的操作请求,由一个goroutine专门负责处理这些请求,从而保证数据一致性。

package main

import (
    "fmt"
    "sync"
)

type Op struct {
    typ  string
    done chan struct{}
}

func worker() {
    var count int
    ch := make(chan Op)
    go func() {
        for op := range ch {
            switch op.typ {
            case "increment":
                count++
                fmt.Println("Incremented count:", count)
            }
            close(op.done)
        }
    }()
    // 模拟其他goroutine发送操作请求
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            done := make(chan struct{})
            ch <- Op{"increment", done}
            <-done
        }()
    }
    wg.Wait()
    close(ch)
}

func main() {
    worker()
}