简介
go语言是一个可以简单实现多核处理的编程语言,使用的协程在kb级别,达到能够实现同时起上w个协程
通过通信来共享资源的Channel
介绍
Channel 是 Go 并发编程的核心工具,用于在协程之间传递数据和协作。通过其阻塞特性和类型安全性,可以实现优雅的协程通信,避免使用锁机制带来的复杂性。
特点
-
类型安全: 一个 channel 只能传递一种类型的数据(定义时指定)。
-
双向通信: 协程之间可以通过 channel 发送和接收数据。
-
阻塞特性: 发送方会阻塞,直到数据被接收。 接收方会阻塞,直到有数据发送到 channel。
-
无锁机制: 使用 channel,可以实现协程之间的数据共享,而不需要显式加锁。
缓冲与不缓冲的区别
在channel中分为有缓冲和不缓冲
- 不缓冲: 是一种同步通讯,需要接收方和传输方同时存在,一个数据一个数据的传送,发送端会阻塞,直到接收端能够接受数据,接收端会阻塞,直到发送端能够发送数据。 代码:
ch := make(chan int) // 创建一个传递 int 类型的无缓冲 channel
- 有缓冲: 可以实现异步通讯,可以在定义缓冲空间中存储数据,不会因为接收端没有准备好而阻塞,也不会因为发送端没准备好而阻塞,只有在缓冲区是否满或者是否空的时候发生阻塞。 代码:
ch := make(chan int, 5) // 创建一个带缓冲区大小为 5 的 channel
实战代码
func CalSquare(){
src := make(chan int)
dest := make(chan int 3)
go func(){
defer close(src)
for i := 0;i<10;i++{
src <- i
}
}()
go func(){
defer close(dest)
for int i := range src{
dest <-i*i
}
}()
for i :=range dest{
println(i)
}
}
通过共享资源来实现通讯
我们在共享资源来实现通讯的时候很容易遇到并发问题,这个时候我们要考虑Lock了
Lock
什么是Lock
Lock 是一种用于协调多个线程或协程对共享资源的访问机制,它通过限制同时访问的线程数量来避免数据竞争。常见的 Lock 类型包括:
- 互斥锁 (Mutex):保证同时只有一个线程能访问共享资源。
- 读写锁 (RWLock):允许多个线程同时读取,但写入时需独占。
- 自旋锁 (Spinlock):线程在等待锁时会持续尝试获取锁,而不是挂起。
- 递归锁 (ReentrantLock):同一个线程可以多次获得同一把锁而不会死锁。
WaitGroup计数器
计数器: 开启协程+1,执行结束-1,主协程阻塞直到计数器等于0
内置方法
- Add(delta int) 计数器+delta
- Done() 计数器-1
- Wait() 阻塞直到计数器为0
实战代码
func ManyGowait(){
var wg sync.WaitGroup
wg.Add(5) // 这里是看你要起多少个协程,我们这里要起5个协程,所以加5
for i := 0;i<5 ;i++{
go func(j int){
defer wg.Done() // 每完成一次就减少一个
hello(j) // 这里其实是实现了一个打印你好
}(i)
}
wg.Wait()
}