MST

星途 面试题库

面试题:Go语言Select语句的执行逻辑与竞争条件处理

在Go语言中,当Select语句中有多个通道操作(如接收或发送)同时准备好时,它的执行逻辑是怎样的?在这种情况下,如何避免潜在的竞争条件?请通过代码示例进行说明。
36.7万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 执行逻辑
    • select语句中有多个通道操作(接收或发送)同时准备好时,Go会随机选择其中一个分支执行。这是为了防止某个通道操作总是优先于其他操作执行,从而保证公平性。
  2. 避免潜在竞争条件
    • 竞争条件通常发生在多个goroutine同时访问和修改共享资源时。为了避免在select语句相关场景中的竞争条件,可以使用互斥锁(sync.Mutex)来保护共享资源,或者使用无锁数据结构(如sync.Map)。
  3. 代码示例
package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    var mu sync.Mutex
    sharedData := 0

    ch1 := make(chan int)
    ch2 := make(chan int)

    // 模拟向通道发送数据
    go func() {
        defer wg.Done()
        ch1 <- 10
    }()

    go func() {
        defer wg.Done()
        ch2 <- 20
    }()

    wg.Add(2)

    select {
    case data := <-ch1:
        mu.Lock()
        sharedData += data
        mu.Unlock()
        fmt.Printf("Received from ch1: %d, Shared data: %d\n", data, sharedData)
    case data := <-ch2:
        mu.Lock()
        sharedData += data
        mu.Unlock()
        fmt.Printf("Received from ch2: %d, Shared data: %d\n", data, sharedData)
    }
}

在上述代码中:

  • 定义了两个通道ch1ch2,并在两个不同的goroutine中向通道发送数据。
  • 使用select语句从两个通道中接收数据。
  • 由于sharedData是共享资源,使用sync.Mutex来保护对sharedData的修改,从而避免竞争条件。无论select语句随机选择哪个分支,都能保证sharedData的安全修改。