面试题答案
一键面试可能出现的问题
在多个goroutine读写共享布尔变量时,会出现竞态条件(race condition)问题。因为多个goroutine可能同时访问和修改这个共享变量,导致最终结果不可预测。例如,一个goroutine在检查变量值后,另一个goroutine在其执行基于该值的操作前修改了这个值,从而引发逻辑错误。
解决方案及代码示例
可以使用sync.Mutex
来解决这个问题。sync.Mutex
提供了一种互斥机制,确保同一时间只有一个goroutine可以访问共享变量。
package main
import (
"fmt"
"sync"
)
var (
serviceRunning bool
mu sync.Mutex
)
func startService(wg *sync.WaitGroup) {
defer wg.Done()
mu.Lock()
if!serviceRunning {
serviceRunning = true
fmt.Println("Service started")
} else {
fmt.Println("Service is already running")
}
mu.Unlock()
}
func stopService(wg *sync.WaitGroup) {
defer wg.Done()
mu.Lock()
if serviceRunning {
serviceRunning = false
fmt.Println("Service stopped")
} else {
fmt.Println("Service is already stopped")
}
mu.Unlock()
}
func main() {
var wg sync.WaitGroup
serviceRunning = false
// 模拟启动服务
wg.Add(1)
go startService(&wg)
// 模拟停止服务
wg.Add(1)
go stopService(&wg)
wg.Wait()
}
代码解释
-
变量定义:
serviceRunning
是共享的布尔变量,用于表示服务的运行状态。mu
是一个sync.Mutex
实例,用于保护对serviceRunning
的访问。
-
startService
函数:defer wg.Done()
确保goroutine结束时通知sync.WaitGroup
。mu.Lock()
锁定互斥锁,阻止其他goroutine同时访问共享变量。- 检查
serviceRunning
的值,如果为false
,则启动服务并打印相应信息;如果为true
,则打印服务已在运行的信息。 mu.Unlock()
解锁互斥锁,允许其他goroutine访问共享变量。
-
stopService
函数:- 同样使用
defer wg.Done()
通知sync.WaitGroup
。 - 锁定互斥锁
mu
,检查serviceRunning
的值,如果为true
,则停止服务并打印相应信息;如果为false
,则打印服务已停止的信息。 - 最后解锁互斥锁。
- 同样使用
-
main
函数:- 初始化
sync.WaitGroup
和serviceRunning
变量。 - 启动两个goroutine,分别调用
startService
和stopService
函数,并通过sync.WaitGroup
等待它们完成。
- 初始化
通过这种方式,使用sync.Mutex
确保了在多个goroutine并发访问共享布尔变量时不会出现竞态条件。