MST

星途 面试题库

面试题:Go中并发与并行在概念上的本质区别是什么

请详细阐述Go语言里并发与并行的本质差异,并且分别举例说明在简单的代码场景中如何体现这种差异。
37.3万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

并发与并行的本质差异

  1. 并发(Concurrency)
    • 本质:并发是一种设计理念,它处理的是多个任务在同一时间段内交替执行的情况。在单核CPU系统中,实际上同一时刻只有一个任务在运行,通过操作系统的调度算法,让多个任务在时间上交替执行,给人一种同时进行的错觉。
    • 举例:假设有两个任务,任务A和任务B。在并发场景下,CPU可能先执行任务A的一部分,然后切换到任务B执行一部分,再切换回任务A,如此循环,使得任务A和任务B看似同时进行。
  2. 并行(Parallelism)
    • 本质:并行意味着多个任务在同一时刻真正地同时执行。这需要多核CPU等硬件支持,每个核心可以独立运行一个任务,从而实现真正的同时处理多个任务。
    • 举例:在多核CPU系统中,如果有两个核心,任务A可以在一个核心上运行,任务B可以在另一个核心上同时运行,这就是并行。

Go语言中简单代码场景体现差异

  1. 并发示例
package main

import (
    "fmt"
    "time"
)

func taskA() {
    for i := 0; i < 5; i++ {
        fmt.Println("Task A:", i)
        time.Sleep(100 * time.Millisecond)
    }
}

func taskB() {
    for i := 0; i < 5; i++ {
        fmt.Println("Task B:", i)
        time.Sleep(100 * time.Millisecond)
    }
}

func main() {
    go taskA()
    go taskB()
    time.Sleep(1000 * time.Millisecond)
}

在这个例子中,通过go关键字启动了两个协程(goroutine)分别执行taskAtaskB。在单核CPU上,它们会交替执行,体现并发。即使在多核CPU上,由于它们的执行时间较短且系统调度等因素,也可能以并发的方式呈现(因为调度器可能会将它们分配到同一个核心上短时间执行)。

  1. 并行示例
package main

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

func taskC(wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < 5; i++ {
        fmt.Println("Task C:", i)
        time.Sleep(100 * time.Millisecond)
    }
}

func taskD(wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < 5; i++ {
        fmt.Println("Task D:", i)
        time.Sleep(100 * time.Millisecond)
    }
}

func main() {
    var wg sync.WaitGroup
    wg.Add(2)
    go taskC(&wg)
    go taskD(&wg)
    wg.Wait()
}

在多核CPU系统下,当启动这两个goroutine(taskCtaskD)时,如果系统调度允许,它们可能会被分配到不同的核心上同时执行,从而体现并行。这里使用sync.WaitGroup来等待两个任务完成,确保程序不会提前退出。