Go语言进阶|青训营

前言

本文从编程的视角来了解Go,包括并发、并行、协程、CSP模型ChannelMutexWaitGrou

并发VS并行

并发:多线程程序在一个核的cpu上运行

image.png
并行:多线程程序在多个核的cpu上运行

image.png
Go语言可以充分发挥多核优势,高效运行

协程Goroutine

image.png

协程:用户态,轻量级线程,栈KB级别

线程:内核态,线程跑多个协程,栈MB级别

一个线程里可以同时执行多个协程,Go可以同时创建上万级别的协程,也是Go支持高并发原因之一。

代码示例

func hello(i int) {  
println("hello world : " + fmt.Sprint(i))  
}  
  
func main() {  
for i := 0; i < 5; i++ {  
// 开启协程  
go hello(i)  
}  
// 等协程执行结束后,主线程再结束  
time.Sleep(time.Second)  
}

CSP(Communicating Sequential Processes)

go语言的最大两个亮点,一个是goroutine,一个就是chan。二者合体的典型应用,基本就是大家认可的并行开发神器,简化了并行程序的开发难度,CSP 是 Communicating Sequential Process 的简称,中文可以叫做通信顺序进程,是一种并发编程模型。

Go语言的CSP模型是由协程Goroutine与通道Channel实现:

  • Go协程goroutine: 是一种轻量线程,它不是操作系统的线程,而是将一个操作系统线程分段使用,通过调度器实现协作式调度。是一种绿色线程,微线程,它与Coroutine协程也有区别,能够在发现堵塞后启动新的微线程。
  • 通道channel: 类似Unix的Pipe,用于协程之间通讯和同步。协程之间虽然解耦,但是它们和Channel有着耦合。

image.png

提倡通过通信共享内存,不提倡通过共享内存实现通信

channel

Channel 分为两种:带缓冲、不带缓冲。对不带缓冲的 channel 进行的操作实际上可以看作 “同步模式”,带缓冲的则称为 “异步模式”。

同步模式

发送方和接收方要同步就绪,只有在两者都 ready 的情况下,数据才能在两者间传输(后面会看到,实际上就是内存拷贝)。否则,任意一方先行进行发送或接收操作,都会被挂起,等待另一方的出现才能被唤醒。

异步模式

在缓冲槽可用的情况下(有剩余容量),发送和接收操作都可以顺利进行。否则,操作的一方(如写入)同样会被挂起,直到出现相反操作(如接收)才会被唤醒。

同步模式下,必须要使发送方和接收方配对,操作才会成功,否则会被阻塞;异步模式下,缓冲槽要有剩余容量,操作才会成功,否则也会被阻塞。

语法格式

make(chan元素类型,【缓冲大小】)

  • 有缓冲通道 make(chan int)
  • 无缓冲通道 make(chan int,2)

image.png

代码示例

A子协程发送0 ~ 9数字,B子协程计算输入数字的平方,主协程输出最后的平方数

并发安全LOCK

Mutex-互斥锁

使用互斥锁能够保证同一时间有且只有一个goroutine进入临界区,其他的goroutine则在等待锁;当互斥锁释放后,等待的goroutine才可以获取锁进入临界区,多个goroutine同时等待一个锁时,唤醒的策略是随机的。Go语言中使用sync包的Mutex类型来实现互斥锁。
Mutex 的实现主要借助了 CAS 指令 + 自旋 + 信号量

Rwmutex-读写锁

对于读多写少的场景下使用读写锁性能会比互斥锁好。
写锁优先级高,写锁独占,读锁共享。
读写锁分为两种:读锁写锁。当一个goroutine获取读锁之后,其他的goroutine如果是获取读锁会继续获得锁,如果是获取写锁就会等待;当一个goroutine获取写锁之后,其他的goroutine无论是获取读锁还是写锁都会等待。

type RWMutex struct {
	w           Mutex	//复用互斥锁提供的能力
	writerSem   uint32	//writer信号量
	readerSem   uint32	//reader信号量
	readerCount int32	//存储了当前正在执行的读操作数量
	readerWait  int32	// 表示写操作阻塞时,等待读操作完成的个数
}

WaitGroup

go 里面的 WaitGroup 是非常常见的一种并发控制方式,它可以让我们的代码等待一组 goroutine 的结束。 比如在主协程中等待几个子协程去做一些耗时的操作,如发起几个 HTTP 请求,然后等待它们的结果。
sync.WaitGroup可以等待一组 Goroutine 的返回

image.png

引用

(Go 语言进阶与依赖管理 – 掘金 (juejin.cn))

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYngVZoB' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片