MST
星途 面试题库

面试题:Go并发编程中,如何简单模拟并发和并行场景并对比其性能

请你编写一段Go代码,分别实现并发和并行的任务执行,并通过合适的方式(如使用`time`包记录执行时间)对比它们在完成相同数量计算任务时的性能差异,简要描述代码思路和观察到的结果。
32.9万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
package main

import (
    "fmt"
    "sync"
    "time"
)

// 并发计算函数
func concurrentCalculation(n int, wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < n; i++ {
        _ = i * i
    }
}

// 并行计算函数
func parallelCalculation(n int, wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < n; i++ {
        _ = i * i
    }
}

func main() {
    numTasks := 1000000
    var wg sync.WaitGroup

    // 并发执行
    startConcurrent := time.Now()
    for i := 0; i < 4; i++ {
        wg.Add(1)
        go concurrentCalculation(numTasks, &wg)
    }
    wg.Wait()
    elapsedConcurrent := time.Since(startConcurrent)

    // 并行执行(这里简单模拟,实际并行依赖于多核CPU调度)
    startParallel := time.Now()
    for i := 0; i < 4; i++ {
        wg.Add(1)
        parallelCalculation(numTasks, &wg)
    }
    wg.Wait()
    elapsedParallel := time.Since(startParallel)

    fmt.Printf("并发执行时间: %s\n", elapsedConcurrent)
    fmt.Printf("并行执行时间: %s\n", elapsedParallel)

    if elapsedConcurrent < elapsedParallel {
        fmt.Println("并发执行更快")
    } else if elapsedConcurrent > elapsedParallel {
        fmt.Println("并行执行更快")
    } else {
        fmt.Println("两者执行时间相同")
    }
}

代码思路

  1. 并发计算:使用go关键字开启多个协程来执行相同的计算任务,通过sync.WaitGroup来等待所有协程完成。
  2. 并行计算:这里简单地通过顺序调用函数来模拟并行(实际并行需要多核CPU支持,且调度由操作系统完成)。
  3. 性能对比:使用time.Now()记录任务开始和结束时间,通过time.Since()计算时间差,从而对比并发和并行执行相同数量计算任务的性能。

观察结果

在多核CPU环境下,通常并发执行会比并行执行(这里简单模拟的顺序执行)更快,因为并发利用了协程的轻量级特性和Go语言的调度器,可以在同一时间片内切换执行不同任务,而并行如果只是简单顺序执行,不能充分利用多核优势。但如果计算任务非常简单且CPU核数有限,可能性能差异不明显,甚至并行执行时间更短(因为协程切换也有开销)。