面试题答案
一键面试可能出现的问题
当闭包在多个 goroutine 中调用并修改共享变量时,会出现竞态条件(race condition)。多个 goroutine 同时访问和修改共享变量,可能导致数据不一致、结果不可预测等问题。
解决方法 - 使用互斥锁(Mutex)
通过互斥锁可以保证同一时间只有一个 goroutine 能够访问共享变量,从而避免竞态条件。
package main
import (
"fmt"
"sync"
)
func main() {
counter := NewCounter()
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
counter.Increment()
}()
}
wg.Wait()
fmt.Println("Final count:", counter.Get())
}
func NewCounter() *Counter {
return &Counter{}
}
type Counter struct {
count int
mu sync.Mutex
}
func (c *Counter) Increment() {
c.mu.Lock()
c.count++
c.mu.Unlock()
}
func (c *Counter) Get() int {
c.mu.Lock()
defer c.mu.Unlock()
return c.count
}
解决方法 - 使用通道(Channel)
可以通过通道来顺序传递修改操作,从而避免竞态条件。
package main
import (
"fmt"
"sync"
)
func main() {
counter := NewCounter()
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
counter.Increment()
}()
}
go func() {
wg.Wait()
close(counter.ops)
}()
for result := range counter.results {
fmt.Println("Final count:", result)
}
}
func NewCounter() *Counter {
c := &Counter{
ops: make(chan func()),
results: make(chan int),
}
go c.run()
return c
}
type Counter struct {
count int
ops chan func()
results chan int
}
func (c *Counter) Increment() {
c.ops <- func() {
c.count++
}
}
func (c *Counter) Get() int {
var result int
c.ops <- func() {
result = c.count
}
return result
}
func (c *Counter) run() {
for op := range c.ops {
op()
}
close(c.results)
c.results <- c.Get()
}