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:创建了多少个协程,就传入相应的deltaDone:当协程运行结束时,调用Done()Wait:该方法用来阻塞直到所有的协程执行结束
然后就可以使用这三个方法来实现主进程的阻塞(以第一个例子为例)
1 | |
Go语言进阶——并发编程
http://example.com/2023/01/16/Go/go-concurrency/