通道是 go 语言中用于在并发函数间安全传递数据的通信机制,提供的数据竞争保护避免直接访问共享内存。通道类型包括无缓冲通道(chan t)和缓冲通道(chan t, int)。规则包括发送值(
Go 语言函数并发编程中的通道类型和规则
通道是 Go 语言中用于在并发函数之间安全地传递数据的通信机制。它们提供了一个抽象层,使函数无需直接访问共享内存,从而避免了数据竞争。
通道类型
- 无缓冲通道 (chan T):此类通道没有内部缓冲区,因此发送方和接收方必须同时处于就绪状态才能进行通信。
- 缓冲通道 (chan T, int):此类通道有一个指定大小的内部缓冲区,用于存储值。它允许发送方在接收方未准备好接收时发送值,反之亦然。
通道规则
-
发送值:使用
send
操作符 () 将值发送到通道。必须先使用 <code> 锁定通道,然后再发送值。
-
接收值:使用
receive
操作符 (->
) 从通道接收值。与发送值类似,必须先使用chan 锁定通道,然后再接收值。
-
关闭通道:使用
close(chan)
关闭通道。关闭后,无法再向通道发送值,但可以继续接收已发送的值。 - 通道容量:缓冲通道有一个指定的最大容量,由创建时指定的第二个参数确定。如果通道已满,发送方将阻塞,直到有空间可用。
-
选择:
select
语句允许从多个通道进行选择性接收或发送。它提供了事件驱动的并发编程模型。
实战案例
考虑一个计算素数的程序:
package main import ( "fmt" "math" "sync" "time" ) // 工作单元 type WorkUnit struct { n uint64 isPrime bool finished chan bool } // 素数计算函数 func isPrime(n uint64) bool { if n <= 1 { return false } for i := uint64(2); i <= uint64(math.Sqrt(float64(n))); i++ { if n%i == 0 { return false } } return true } // 工作器函数 func worker(in, out chan *WorkUnit, wg *sync.WaitGroup) { defer wg.Done() for unit := range in { unit.isPrime = isPrime(unit.n) close(unit.finished) out <- unit } } func main() { // 输入通道 in := make(chan *WorkUnit) // 输出通道 out := make(chan *WorkUnit) // 初始化工作单元 units := make([]*WorkUnit, 500000) for i := range units { units[i] = &WorkUnit{ n: uint64(i), finished: make(chan bool), } } // 启动工作器 wg := &sync.WaitGroup{} for i := 0; i < 5; i++ { wg.Add(1) go worker(in, out, wg) } // 将工作单元推送到输入通道 start := time.Now() for _, unit := range units { in <- unit } close(in) // 从输出通道接收结果 for unit := range out { <-unit.finished } elapsed := time.Since(start) fmt.Printf("Took %sn", elapsed) }
登录后复制
在这个示例中:
-
in
通道是无缓冲通道,用于将工作单元发送到工作器函数。 -
out
通道是缓冲通道,用于将计算结果传回主函数。 -
finished
通道是一个无缓冲通道,用于在工作器函数完成计算后向主函数发出信号。
该程序演示了如何在 Go 中使用通道来实现并发计算,有效地利用了多个 CPU 核心。
以上就是Golang函数并发编程中通道的类型和规则的详细内容,更多请关注叮当号网其它相关文章!
文章来自互联网,只做分享使用。发布者:周斌,转转请注明出处:https://www.dingdanghao.com/article/367222.html