较快者等待较慢者发出通知

2021年11月23日 阅读数:6
这篇文章主要向大家介绍较快者等待较慢者发出通知,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

 

通道用例大全 - Go语言101(通俗版Go白皮书) https://gfw.go101.org/article/channel-use-cases.htmlhtml

使用通道实现通知

通知能够被看做是特殊的请求/回应用例。在一个通知用例中,咱们并不关心回应的值,咱们只关心回应是否已发生。 因此咱们经常使用空结构体类型struct{}来作为通道的元素类型,由于空结构体类型的尺寸为零,可以节省一些内存(虽然经常不多量)。并发

向一个通道发送一个值来实现单对单通知

咱们已知道,若是一个通道中无值可接收,则此通道上的下一个接收操做将阻塞到另外一个协程发送一个值到此通道为止。 因此一个协程能够向此通道发送一个值来通知另外一个等待着今后通道接收数据的协程。ui

在下面这个例子中,通道 done被用来作为一个信号通道来实现单对单通知。
package main

import (
	"crypto/rand"
	"fmt" "os" "sort" ) func main() { values := make([]byte, 32 * 1024 * 1024) if _, err := rand.Read(values); err != nil { fmt.Println(err) os.Exit(1) } done := make(chan struct{}) // 也能够是缓冲的 // 排序协程 go func() { sort.Slice(values, func(i, j int) bool { return values[i] < values[j] }) done <- struct{}{} // 通知排序已完成 }() // 并发地作一些其它事情... <- done // 等待通知 fmt.Println(values[0], values[len(values)-1]) } 

 

从一个通道接收一个值来实现单对单通知

若是一个通道的数据缓冲队列已满(非缓冲的通道的数据缓冲队列老是满的)但它的发送协程队列为空,则向此通道发送一个值将阻塞,直到另一个协程今后通道接收一个值为止。 因此咱们能够经过从一个通道接收数据来实现单对单通知。通常咱们使用非缓冲通道来实现这样的通知。spa

这种通知方式不如上例中介绍的方式使用得普遍。code

package main

import (
	"fmt"
	"time" ) func main() { done := make(chan struct{}) // 此信号通道也能够缓冲为1。若是这样,则在下面 // 这个协程建立以前,咱们必须向其中写入一个值。 go func() { fmt.Print("Hello") // 模拟一个工做负载。 time.Sleep(time.Second * 2) // 使用一个接收操做来通知主协程。 <- done }() done <- struct{}{} // 阻塞在此,等待通知 fmt.Println(" world!") } 

 

另外一个事实是,上面的两种单对单通知方式其实并无本质的区别。 它们均可以被归纳为较快者等待较慢者发出通知协程