关于Go语言的并发|青训营笔记

194 阅读2分钟

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

前言

参与青训营课程的学习,我将课程中自己比较有收获的东西进行了整理和总结,用以日后复习和查阅,如果对各位读者有帮助,实属我的荣幸,也希望大家能够不吝赐教,指出我学习中存在的问题,多多交流。

关于Go的并发

并发的概念

image.png 在学习操作系统这门课程的过程中,仅强调了并发的一些知识,但在如今CPU多核的硬件条件下,使用并行将性能发挥到极致也是我们需要掌握的,而go语言高性能的原因,其中之一就体现在这个并发性上面

协程Goroutine

  • 众所周知,线程是CPU调度和分配的基本单位,被操作系统内核所管理,运行在内核态;
  • 而协程是一种比线程更加轻量级的存在,并且完全由程序所控制。

image.png

通道Channel

image.png

  • 通道可以理解成一个对信息进行传输的工具
  • 有缓冲通道相对于无缓冲通道的一大优势是:当通道双方的收发速度不一致时,缓冲通道可以一定程度避免因为一方的速度慢导致的整个速度降低,可以更“快”

并发安全Lock

package concurrence

import (
   "sync"
   "time"
)

var (
   x    int64
   lock sync.Mutex
)

/*
测试使用lock和不使用lock对并发程序结果的影响
*/
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)
}

/*
output:
  第一次
   === RUN   TestAddLock
   WithoutLock: 8882
   WithLock: 10000
   --- PASS: TestAddLock (2.01s)
 多次运行后:???
   === RUN   TestAddLock
   WithoutLock: 10000
   WithLock: 10000
   --- PASS: TestAddLock (2.02s)
*/
  • 而令我疑惑的是,为什么在多次运行测试代码后,有lock和无lock两者的结果一致了?