MST

星途 面试题库

面试题:Go函数调用惯例与并发编程

Go语言以其出色的并发编程能力闻名。结合Go函数调用的调用惯例,阐述在并发环境下函数调用可能会遇到的问题,比如资源竞争。如何通过合适的同步机制(如互斥锁、通道等)来解决这些问题?请给出具体的代码示例并解释。
45.4万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

并发环境下函数调用的问题

  1. 资源竞争:当多个goroutine同时访问和修改共享资源时,会发生资源竞争。例如多个goroutine同时对一个全局变量进行读写操作,可能导致数据不一致。

解决方法及代码示例

  1. 使用互斥锁(Mutex)
    • 互斥锁用于保证在同一时刻只有一个goroutine能够访问共享资源。
    • 示例代码如下:
package main

import (
    "fmt"
    "sync"
)

var (
    counter int
    mu      sync.Mutex
)

func increment(wg *sync.WaitGroup) {
    defer wg.Done()
    mu.Lock()
    counter++
    mu.Unlock()
}

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 1000; i++ {
        wg.Add(1)
        go increment(&wg)
    }
    wg.Wait()
    fmt.Println("Final counter value:", counter)
}
- 在这段代码中,`counter` 是共享资源,`mu` 是互斥锁。`increment` 函数在访问和修改 `counter` 之前先锁定 `mu`,操作完成后解锁,这样就避免了资源竞争。

2. 使用通道(Channel): - 通道可以用于在goroutine之间传递数据,并且可以用来同步goroutine的执行。 - 示例代码如下:

package main

import (
    "fmt"
)

func sendData(ch chan int) {
    for i := 1; i <= 5; i++ {
        ch <- i
    }
    close(ch)
}

func receiveData(ch chan int) {
    for data := range ch {
        fmt.Println("Received:", data)
    }
}

func main() {
    ch := make(chan int)
    go sendData(ch)
    receiveData(ch)
}
- 在这个例子中,`sendData` 函数通过通道 `ch` 发送数据,`receiveData` 函数从通道接收数据。通道的使用确保了数据发送和接收的同步,避免了并发访问的问题。通过 `range` 循环读取通道数据,直到通道被关闭,保证了数据的完整接收。