MST

星途 面试题库

面试题:Go中反射操作并发对象之基础同步问题

在Go语言中,使用反射操作并发对象时,为了防止数据竞争,通常会使用哪些同步机制?请举例说明如何结合反射和这些同步机制来安全地操作并发对象。
13.5万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

在Go语言中,使用反射操作并发对象时,为防止数据竞争,通常使用以下同步机制:

  1. 互斥锁(sync.Mutex:用于保护共享资源,同一时间只有一个goroutine能访问被保护的资源。
    package main
    
    import (
        "fmt"
        "reflect"
        "sync"
    )
    
    type MyStruct struct {
        Value int
    }
    
    var mu sync.Mutex
    var obj MyStruct
    
    func updateObject(newVal int) {
        mu.Lock()
        defer mu.Unlock()
    
        v := reflect.ValueOf(&obj).Elem()
        field := v.FieldByName("Value")
        if field.IsValid() && field.CanSet() {
            field.SetInt(int64(newVal))
        }
    }
    
    func main() {
        var wg sync.WaitGroup
        for i := 0; i < 10; i++ {
            wg.Add(1)
            go func(val int) {
                defer wg.Done()
                updateObject(val)
            }(i)
        }
        wg.Wait()
        fmt.Println(obj.Value)
    }
    
  2. 读写锁(sync.RWMutex:适用于读多写少的场景,允许多个goroutine同时读,但写操作时会独占资源。
    package main
    
    import (
        "fmt"
        "reflect"
        "sync"
    )
    
    type MyStruct struct {
        Value int
    }
    
    var rwmu sync.RWMutex
    var obj MyStruct
    
    func readObject() int {
        rwmu.RLock()
        defer rwmu.RUnlock()
    
        v := reflect.ValueOf(&obj).Elem()
        field := v.FieldByName("Value")
        if field.IsValid() {
            return int(field.Int())
        }
        return 0
    }
    
    func writeObject(newVal int) {
        rwmu.Lock()
        defer rwmu.Unlock()
    
        v := reflect.ValueOf(&obj).Elem()
        field := v.FieldByName("Value")
        if field.IsValid() && field.CanSet() {
            field.SetInt(int64(newVal))
        }
    }
    
    func main() {
        var wg sync.WaitGroup
        for i := 0; i < 5; i++ {
            wg.Add(1)
            go func(val int) {
                defer wg.Done()
                writeObject(val)
            }(i)
        }
        for i := 0; i < 10; i++ {
            wg.Add(1)
            go func() {
                defer wg.Done()
                fmt.Println(readObject())
            }()
        }
        wg.Wait()
    }
    
  3. 通道(chan:通过通信来共享内存,而不是共享内存来通信。
    package main
    
    import (
        "fmt"
        "reflect"
        "sync"
    )
    
    type MyStruct struct {
        Value int
    }
    
    var obj MyStruct
    var updateChan = make(chan int)
    
    func updateObject() {
        for newVal := range updateChan {
            v := reflect.ValueOf(&obj).Elem()
            field := v.FieldByName("Value")
            if field.IsValid() && field.CanSet() {
                field.SetInt(int64(newVal))
            }
        }
    }
    
    func main() {
        var wg sync.WaitGroup
        go updateObject()
        for i := 0; i < 10; i++ {
            wg.Add(1)
            go func(val int) {
                defer wg.Done()
                updateChan <- val
            }(i)
        }
        wg.Wait()
        close(updateChan)
        fmt.Println(obj.Value)
    }