MST

星途 面试题库

面试题:Go并发编程并发与并行负载均衡实现方式

在Go并发编程中,如何利用goroutine和channel实现简单的并发负载均衡?如果要扩展到并行负载均衡,又需要做哪些调整?请给出代码示例并解释其原理。
40.0万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

简单并发负载均衡

  1. 原理:通过goroutine来并行处理任务,channel用于在不同goroutine之间传递任务和结果。主goroutine将任务发送到任务channel,多个工作goroutine从任务channel中接收任务并处理,处理结果通过结果channel返回。
  2. 代码示例
package main

import (
    "fmt"
)

func worker(id int, tasks <-chan int, results chan<- int) {
    for task := range tasks {
        fmt.Printf("Worker %d started task %d\n", id, task)
        result := task * task
        fmt.Printf("Worker %d finished task %d with result %d\n", id, task, result)
        results <- result
    }
}

func main() {
    const numWorkers = 3
    const numTasks = 5

    tasks := make(chan int, numTasks)
    results := make(chan int, numTasks)

    // 启动工作goroutine
    for i := 0; i < numWorkers; i++ {
        go worker(i, tasks, results)
    }

    // 发送任务
    for i := 0; i < numTasks; i++ {
        tasks <- i
    }
    close(tasks)

    // 收集结果
    for i := 0; i < numTasks; i++ {
        fmt.Printf("Result: %d\n", <-results)
    }
    close(results)
}

扩展到并行负载均衡

  1. 原理:并行负载均衡意味着在不同的计算资源(如多核CPU)上并行执行任务。Go语言的运行时系统会自动将goroutine调度到多个操作系统线程上,充分利用多核资源。为了更好地利用多核,可以适当增加工作goroutine的数量,并且合理分配任务,避免某个goroutine负载过重。
  2. 代码示例调整
package main

import (
    "fmt"
    "runtime"
)

func worker(id int, tasks <-chan int, results chan<- int) {
    for task := range tasks {
        fmt.Printf("Worker %d started task %d\n", id, task)
        result := task * task
        fmt.Printf("Worker %d finished task %d with result %d\n", id, task, result)
        results <- result
    }
}

func main() {
    // 设置最大的CPU核数使用数
    runtime.GOMAXPROCS(runtime.NumCPU())

    const numWorkers = runtime.NumCPU() * 2
    const numTasks = 10

    tasks := make(chan int, numTasks)
    results := make(chan int, numTasks)

    // 启动工作goroutine
    for i := 0; i < numWorkers; i++ {
        go worker(i, tasks, results)
    }

    // 发送任务
    for i := 0; i < numTasks; i++ {
        tasks <- i
    }
    close(tasks)

    // 收集结果
    for i := 0; i < numTasks; i++ {
        fmt.Printf("Result: %d\n", <-results)
    }
    close(results)
}

在上述代码中,通过runtime.GOMAXPROCS(runtime.NumCPU())设置Go运行时使用的最大CPU核数,numWorkers设置为CPU核数的两倍,以更好地利用多核资源进行并行处理。这样在多核CPU环境下,任务可以并行执行,实现并行负载均衡。