MST

星途 面试题库

面试题:Go布尔类型在并发编程中的特殊应用及问题处理

在Go的并发编程场景下,有多个goroutine需要读写一个共享的布尔类型变量来控制程序流程(例如控制某个服务的启停)。请描述可能会出现的问题,并给出使用Go语言特性(如sync包中的工具)来解决这些问题的完整代码示例及详细解释。
35.8万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

可能出现的问题

在多个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()
}

代码解释

  1. 变量定义

    • serviceRunning 是共享的布尔变量,用于表示服务的运行状态。
    • mu 是一个sync.Mutex实例,用于保护对serviceRunning的访问。
  2. startService函数

    • defer wg.Done() 确保goroutine结束时通知sync.WaitGroup
    • mu.Lock() 锁定互斥锁,阻止其他goroutine同时访问共享变量。
    • 检查serviceRunning的值,如果为false,则启动服务并打印相应信息;如果为true,则打印服务已在运行的信息。
    • mu.Unlock() 解锁互斥锁,允许其他goroutine访问共享变量。
  3. stopService函数

    • 同样使用defer wg.Done() 通知sync.WaitGroup
    • 锁定互斥锁mu,检查serviceRunning的值,如果为true,则停止服务并打印相应信息;如果为false,则打印服务已停止的信息。
    • 最后解锁互斥锁。
  4. main函数

    • 初始化sync.WaitGroupserviceRunning变量。
    • 启动两个goroutine,分别调用startServicestopService函数,并通过sync.WaitGroup等待它们完成。

通过这种方式,使用sync.Mutex确保了在多个goroutine并发访问共享布尔变量时不会出现竞态条件。