面试题答案
一键面试并发与并行的本质差异
- 并发(Concurrency):
- 本质:并发是一种设计理念,它处理的是多个任务在同一时间段内交替执行的情况。在单核CPU系统中,实际上同一时刻只有一个任务在运行,通过操作系统的调度算法,让多个任务在时间上交替执行,给人一种同时进行的错觉。
- 举例:假设有两个任务,任务A和任务B。在并发场景下,CPU可能先执行任务A的一部分,然后切换到任务B执行一部分,再切换回任务A,如此循环,使得任务A和任务B看似同时进行。
- 并行(Parallelism):
- 本质:并行意味着多个任务在同一时刻真正地同时执行。这需要多核CPU等硬件支持,每个核心可以独立运行一个任务,从而实现真正的同时处理多个任务。
- 举例:在多核CPU系统中,如果有两个核心,任务A可以在一个核心上运行,任务B可以在另一个核心上同时运行,这就是并行。
Go语言中简单代码场景体现差异
- 并发示例:
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)分别执行taskA
和taskB
。在单核CPU上,它们会交替执行,体现并发。即使在多核CPU上,由于它们的执行时间较短且系统调度等因素,也可能以并发的方式呈现(因为调度器可能会将它们分配到同一个核心上短时间执行)。
- 并行示例:
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(taskC
和taskD
)时,如果系统调度允许,它们可能会被分配到不同的核心上同时执行,从而体现并行。这里使用sync.WaitGroup
来等待两个任务完成,确保程序不会提前退出。