go语言| 青训营笔记

66 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天

并行vs并发

image.png go语言可以充分发挥多核优势,高并发运行。

线程和协程

线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。一个进程可以有一个或多个线程,各个线程之间共享程序的内存空间(也就是所在进程的内存空间)。一个标准的线程由线程ID、当前指令指针(PC)、寄存器和堆栈组成。而进程由内存空间(代码、数据、进程空间、打开的文件)和一个或多个线程组成。

image.png

CSP

CSP 并发模型是上个世纪七十年代提出的,用于描述两个独立的并发实体通过共享 channel(管道)进行通信的并发模型。

Go语言就是借用 CSP 并发模型的一些概念为之实现并发的,但是Go语言并没有完全实现了 CSP 并发模型的所有理论,仅仅是实现了 process 和 channel 这两个概念。

process 就是Go语言中的 goroutine,每个 goroutine 之间是通过 channel 通讯来实现数据共享。

image.png

并发安全与lock

在我们的项目中,可能会存在多个goroutine同时操作一个资源(临界区),这种情况会发生竞态问题(数据竞态)。

互斥锁

互斥锁能够保证同时只有一个goroutine可以访问共享资源,是一种常用的控制共享资源访问的方法。Go语言中使用sync包的Mutex类型来实现互斥锁。

// 多个goroutine并发操作全局变量x
var x int64
var wg sync.WaitGroup
var lock sync.Mutex // 互斥锁

func add()  {
    for i :=0;i<1000;i++{
        lock.Lock()     // 加锁
        x = x + 1
        lock.Unlock()   // 解锁
    }
    wg.Done()
}
func main()  {
    wg.Add(2)
    go add()
    go add()
    wg.Wait()
    fmt.Println(x)
}