面试题答案
一键面试原因分析
- 竞态条件问题:这段代码中多个goroutine同时对
count
进行读写操作,由于没有同步机制,会导致竞态条件。在多个goroutine并发执行count++
时,count++
并非原子操作,它通常分为读取count
的值、对值加1、再将结果写回count
三个步骤。当多个goroutine同时执行这三个步骤时,可能会出现一个goroutine读取count
的值后,另一个goroutine也读取了相同的值,然后两个goroutine分别加1并写回,这样就会丢失一次累加,导致最终结果小于1000。
修改代码
package main
import (
"fmt"
"sync"
)
var count int
var wg sync.WaitGroup
func main() {
for i := 0; i < 1000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
var mu sync.Mutex
mu.Lock()
count++
mu.Unlock()
}()
}
wg.Wait()
fmt.Println(count)
}
在上述修改后的代码中:
sync.WaitGroup
:用于等待所有goroutine完成。在启动每个goroutine前调用wg.Add(1)
增加等待组计数器,在goroutine结束时调用wg.Done()
减少计数器。最后通过wg.Wait()
阻塞主线程,直到所有goroutine执行完毕。sync.Mutex
:用于同步对count
的访问。在对count
进行累加操作前,通过mu.Lock()
加锁,操作完成后通过mu.Unlock()
解锁,确保同一时间只有一个goroutine能够对count
进行读写操作,避免竞态条件。