Golang中Channel简介
Go语言中的channel
是一种核心的并发控制结构,它允许在不同的goroutine
之间同步和传递数据。以下是channel
的一些基本特性:
channel
是一种类型,可以用于在goroutine
之间传递数据。- 通过
make
函数创建channel
,例如ch := make(chan string)
创建了一个用于传递字符串的channel
。 channel
有三种基本操作:发送、接收和关闭,发送操作使用ch <- x
,接收操作使用x := <-ch
或<-ch
。channel
分为有缓冲和无缓冲两种。无缓冲channel
在读写过程中都会阻塞,直到发送和接收操作都准备好。有缓冲channel
在缓冲区满时写操作会阻塞,空时读操作会阻塞。无缓冲channel
是同步的,发送和接收操作必须同时准备好。有缓冲channel
是异步的,写操作在缓冲区未满时直接返回,读操作在缓冲区不空时进行。channel
可以被关闭,关闭后不能再进行发送操作,但可以继续进行接收操作直到缓冲区的数据被读完。channel
的容量是make
函数中指定的缓冲区大小,长度是当前缓冲区中的数据数量。channel
可能会导致循环阻塞或协程泄漏,需要特别注意使用方法以防止死锁和协程泄漏的产生。
Golang使用Channel实现并发控制
代码demo
package main
import (
"fmt"
"sync"
"time"
)
// 定义协程池
type ThreadPool struct {
ch chan int
}
// 创建协程池,含最大并发量参数
func NewThreadPool(maxCoroutines int) *ThreadPool {
return &ThreadPool{
ch: make(chan int, maxCoroutines),
}
}
// 从协程池获取协程,以处理任务
func (tp *ThreadPool) Get() {
tp.ch <- 1
}
// 任务完成后,归还协程至协程池
func (tp *ThreadPool) Put() {
<-tp.ch
}
func main() {
maxCoroutines := 5
tp := NewThreadPool(maxCoroutines)
wg := sync.WaitGroup{}
for i := 0; i < 50; i++ {
tp.Get()
wg.Add(1)
go func(i int) {
defer func() {
wg.Done()
tp.Put()
}()
time.Sleep(100 * time.Microsecond)
fmt.Println("idx ", i)
}(i)
}
wg.Wait()
fmt.Println("finish")
}
代码解读
- 使用带缓冲的
channel
实现最大并发量的控制。- 通过
NewThreadPool(maxCoroutines int)
创建最大并发量为maxCoroutines
的协程池。 - 协程池的
Get()
方法,向带缓冲的channel
中写入数据,作用是获取空闲协程池来处理任务; 若chnanel
已满则阻塞,实现最大并发量控制。 - 协程池的
Put()
方法,从带缓冲的channel
中获取数据,作用是释放资源池,增加新的可用协程。
- 通过
- 使用
sync.WaitGroup
等待所有任务结束。- 任务开始时使用
sync.WaitGroup.Add(1)
方法增加任务计数。 - 任务结束时使用
sync.WaitGroup.Done()
方法减少任务计数,减少1。 - 最后使用
sync.WaitGroup.Wait()
方法等待所有任务完成。
- 任务开始时使用