一、并发与并行
并行是指在同一时刻,有多条指令在多个处理器上同时执行,每个任务都在不同的处理器核心上进行操作。在并行模型下,多个任务可以同时执行,并通过多核或多处理器来实现加速执行。对于需要大量计算的任务,并行模式可以显著提高计算性能。
并发是指在同一时间内,有若干个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,系统通过时间片轮转等机制,使多个进程快速交替执行。这样的执行方式可以提高系统的效率,因为当一个任务需要等待某些资源时,其他任务可以继续执行,不会造成系统的停滞。
二、线程与协程
线程从属于进程,是程序的实际执行者,一个进程至少包含一个主线程,也可以有更多的子线程,线程拥有自己的栈空间。
对操作系统而言,线程是最小的执行单元,进程是最小的资源管理单元。无论是进程还是线程,都是由操作系统所管理的。
协程是一种比线程更加轻量级的存在,正如一个进程可以拥有多个线程一样,一个线程可以拥有多个协程。协程不是被操作系统内核所管理的,而是完全由程序所控制,也就是在用户态执行。这样带来的好处是性能大幅度的提升,因为不会像线程切换那样消耗资源。
三、并发安全Lock
因为Go语言存在通过共享内存实现通道,因此会出现多种路径同时操作同一块内存的情况。
通过对临界区加锁来保证并发安全。
For example:
对变量执行2000次+1操作,5个协程并发执行。
package main
import (
"sync"
"time"
)
var (
x int64
lock sync.Mutex
)
func addWithLock() {
for i := 0; i < 2000; i++ {
lock.Lock()
x += 1
lock.Unlock()
}
}
func addWithoutLock() {
for i := 0; i < 2000; i++ {
x += 1
}
}
func Add() {
x = 0
for i := 0; i < 5; i++ {
go addWithoutLock()
}
time.Sleep(time.Second)
println("WithoutLock:", x)
x = 0
for i := 0; i < 5; i++ {
go addWithLock()
}
time.Sleep(time.Second)
println("WithLock:", x)
}
func main() {
Add()
}
输出: