面试题答案
一键面试在Go语言中,使用反射操作并发对象时,为防止数据竞争,通常使用以下同步机制:
- 互斥锁(
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) }
- 读写锁(
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() }
- 通道(
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) }