Go语言进阶——并发编程
并发与并行
- 并发:多个线程通过切换时间片的方式在一个
cpu
上进行调度运行 - 并行:多个线程在
cpu
的多个核上运行,真正的同时运行
线程与协程
- 线程:内核态,操作系统内核进行调度的基本单位,在一个线程上可以跑多个携程,栈大小在MB级别
- 协程:用户态,由
Go
管理,轻量级线程,栈大小在KB级别
Go
中使用go
语句创建协程
1 |
|
输入如下
可以看到输出并不是顺序的,说明确实协程是并发执行的
CSP
- 通过通信共享内存:通过通道的方式实现进程之间信息的交换(
Go
语言提倡) - 通过共享内存实现通信:操作系统中进程通信的经典方式,通过读写信号量实现对临界区内存的正确访问
Channel
make(chan <eleType>, [size])
- 无缓冲通道:
make(chan int)
- 有缓冲通道:
make(chan int, 2)
1 |
|
Lock
使用信号量的方式对临界区的访问进行控制,使得并发的协程能够正确访问临界区
1 |
|
测试是各创建5个协程调用上述两个方法,结果如下
可以看到加锁方法可以保证每次都正确得到结果;但是不加锁的方法每次得到的结果是不确定的
WaitGroup
前面在主线程创建了协程之后,主线程是使用time.Sleep()
方法来阻塞自己的,但是这并不是一个好的方法,因为我们并不知道协程到底什么时候执行结束,我们只能传入一个大概的比较大的值进去。
sync
包下有一个结构体:WaitGroup
,可以通过该方法优雅地实现主进程的阻塞
该结构体内部维护了一个计数器,并且暴露了三个方法出来
Add
:创建了多少个协程,就传入相应的delta
Done
:当协程运行结束时,调用Done()
Wait
:该方法用来阻塞直到所有的协程执行结束
然后就可以使用这三个方法来实现主进程的阻塞(以第一个例子为例)
1 |
|
Go语言进阶——并发编程
http://example.com/2023/01/16/Go/go-concurrency/