当前位置: 首页 > news >正文

建站之星app今天特大新闻最新消息

建站之星app,今天特大新闻最新消息,wordpress+分页静态,创意经济型网站建设channel 是什么? channel 是GO语言中一种特殊的类型,是连接并发goroutine的管道 channel 通道是可以让一个 goroutine 协程发送特定值到另一个 goroutine 协程的通信机制。 关于 channel 的原理,channel通道需要注意的地方,之前…

channel 是什么?

channel 是GO语言中一种特殊的类型,是连接并发goroutine的管道

channel 通道是可以让一个 goroutine 协程发送特定值到另一个 goroutine 协程的通信机制

关于 channel 的原理,channel通道需要注意的地方,之前有分享过,可以查看如下文章

  1. GO通道和 sync 包的分享
  2. GO 中 channel 实现原理

本次,我们主要分享的是关于 nil channel 通道,有缓冲通道,无缓冲通道 的常用方法以及巧妙使用的方式

巧用 nil 的 channel 通道

平日里使用的 channel 通道都是使用无缓冲,或者有缓冲的 channel 通道,或许使用为 nil 的 channel 通道还是比较少,甚至都不知道如何去使用 nil 的 channel 通道

我们先来看这么一个例子

  1. 创建两个 channel c1, c2 ,数据类型是 struct{} ,用于占位
  2. 分别开辟两个子协程,其中子协程 1 在 2 秒之后写入数据给到 c1,另外一个子协程 2 在 1 秒之后写入数据给到 c2
  3. 主协程循环等待阻塞读取 c1 , c2 里面的数据,读取后将对应的标识 ok1 / ok2 置为 true
  4. 当 ok1 和 ok2 都为 true 的时候,退出循环,结束程序
func main() {c1, c2 := make(chan struct{}), make(chan struct{})go func() {time.Sleep(time.Second * 2)c1 <- struct{}{}//close(c1)}()go func() {time.Sleep(time.Second * 1)c2 <- struct{}{}// close(c2)}()var (ok1 boolok2 bool)for {select {case <-c1:ok1 = truefmt.Println("1")case <-c2:ok2 = truefmt.Println("2")}if ok1 && ok2 {break}}fmt.Println("program termination ... ")
}

运行结果如下:

2
1
program termination ...

看上去效果一切正常,若此时,我们将上述代码中的 close(c1)close(c2) 的注释去掉,我们再查看一下结果就回是这样的:

...
2
2
2
1
program termination ...

出现这样的问题是什么呢?是因为我们 close channel 通道之后,若还对这个通道写入数据会 panic,若还从这个通道读取数据会立即返回该通道类型的零值,而不会阻塞等待数据

因此才会有上述情况,那么这个时候,我就可以很好的用好这个 nil 的 channel,咱就可以这样来调整一下关于通道使用的情况

修改为,从通道中读取数据时,先判断通道是否已经关闭,若关闭则将通道设置为 nil,若未关闭,则打印我们从通道中读取的数据(此处模拟直接打印一个固定的值)

for {select {case _, ok := <-c1:if !ok {c1 = nil}else{fmt.Println("1")}case _, ok := <-c2:if !ok {c2 = nil}else{fmt.Println("2")}}if c1 == nil && c2 == nil {break}
}

这种时候,我们就知道对于从通道中读取数据,先去判断通道是否关闭,若通道关闭了,那么我们直接显示的给通道设置为 nil

这里是否会有这么一个疑问?关闭通道,通道变量不应该就变成 nil 了吗?为什么我们还要自己去设置为 nil?

实际上这就是我们对于通道的基础知识不扎实了,关闭通道后,通道本身并不会变为 nil。通道变量仍然持有通道的地址,只是通道的状态变为了已关闭

巧用无缓冲 channel 通道

对于无缓冲的 channel 通道,只有在对其进行接收操作的 goroutine 协程和对其进行发送操作的 goroutine 协程都存在的情况下,通信才能进行,否则单方面的操作会让对应的 goroutine 协程陷入阻塞状态,因为该 channel 通道没有缓冲

使用无缓冲的 channel 通道,我们可以用在如下几个方面

  1. 信号传递

信号传递我们就可以用在两个协程一对一的传递信号上面,当然我们也可以使用在主协程主动通知所有子协程关闭的全场景下,这就是一对多的传递信号,相关的 demo 可以在这期文章中有展示

GO 语言的并发模式

一对一(一个发一个收)

一对多(一个发多个收,此处可以是 协程 1 close 掉 通道,那么 多个协程默认都能够读取到通道的值是零值,此时多个子协程就可以根据通道的关闭状态来处理后续的逻辑)

  1. 控制同步

GO语言倡导我们不要通过共享内存来通信,而应该通过通信来共享内存,此处 channel 就是这样设计的,当然如果需要有更高的性能,那么我们还是可以使用更加低级的GO语言原语 sync 包中的锁机制

可以点击查看往期文章:sync 锁机制

巧用有缓冲 channel 通道

  1. 用作队列

用作队列应该是比较好理解的,队列先入先出 FIFO,给 channel 通道设置明确的缓冲区,例如 ch:=make(chan int, 10)

多个协程就可以异步的并发处理该队列,由于有缓冲的 channel 通道中有一定的容量,因此,对于协程读取通道中数据时,存在阻塞的情况相对无缓冲的通道来说就会少很多,相应的在一定程度上就提升了性能

对于有缓冲的 channel 通道,channel 通道满的时候,写入数据会阻塞,读取数据正常处理, channel 通道空的时候,写入数据正常,读取数据会阻塞

  1. 用作信号量

有缓冲的 channel 通道还可以用来计数,例如我们有 15 个 job,可是目前只有 3 个 worker,那么同一时间,只会有 3 个worker 来干活,我们就可以使用通道来查看目前有多少个 worker 在工作,写一个简单的 demo

  • 创建 j 和 worker channel 通道,
  • 子协程 1 写 15 个任务给到 j 通道中,写完 15 个任务到 j 中便关闭自己的通道(因为后续我们需要使用 for…range 的方式读取通道)
  • 使用 sync.WaitGroup 管控开辟的 3 个协程,模拟 3 个 工人去干活
  • 能够从写入数据到 worker channel 通道中,则开始干活,干完之后,从 worker channel 通道中读出数据
func main() {j := make(chan int, 15)worker := make(chan int, 3)go func() {for i := 0; i < 15; i++ {j <- i}close(j)}()var wg sync.WaitGroupfor job := range j {wg.Add(1)go func(job int) {defer wg.Done()worker <- job// 模拟干活fmt.Println("正在执行 job : ", job)time.Sleep(time.Second * 1)<-worker}(job)}wg.Wait()fmt.Println("program termination ... ")
}

感兴趣的 xdm 的可以复制代码运行一下,可以看到效果是 3 个 job 一起打印,间隔 1 秒后,又是 3 个 job 一起打印的😁

select 和 channel 通道如何结合使用?

  1. 心跳
func main() {h := time.NewTicker(2 * time.Second)defer h.Stop()for {select {case <-h.C:// 模拟处理心跳fmt.Println("hhh")}}
}
  1. 使用 default

select ...default 这个组合就不必过多赘述了,就是在我们阻塞读取通道数据时,若当前时间没有从任何一个通道中读取到数据,则默认走 default 里面的逻辑

  1. 超时机制

超时机制使用的也是非常频繁的,很多时候为了方便,可能我们会使用例如<- time.After(10 * time.Second) 的方式,使用这种方式,GO 语言会维护一个最小堆,当时间到了,通道被唤醒的时候,就会从最小堆顶取出 timer 对象,再执行 timer 中的函数,执行完毕之后,自行就会做删除,自行就会做 GC

可是在上述这种方式使用比较多的时候,会给程序带来 GC 的压力,我们完全可以入如下方式来实现超时机制,显示的去做 GC

func main() {c := time.NewTimer(10 * time.Second)defer c.Stop()for {select {case <-c.C:fmt.Println("program overtime ")return}}
}

总结

本次演示了关于 nil channel,有缓冲 channel ,无缓冲 channel , select 如何与 channel 配合使用,上述 demo 完全可以复制下来,xdm 可以自行运行,查看效果

欢迎点赞,关注,收藏

朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力

好了,本次就到这里

技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。

我是阿兵云原生,欢迎点赞关注收藏,下次见~
可以进入地址进行体验和学习:https://xxetb.xet.tech/s/3lucCI

http://www.zhongyajixie.com/news/20318.html

相关文章:

  • 陕西电商b2c网站建设公司网站建设开发公司
  • 广东建设工程执业资格注册中心网站google chrome官网下载
  • 网站反链接百度竞价教程
  • wordpress没有安装主题选项卡企业网站seo平台
  • 崇明做网站公司广州网页seo排名
  • 网站开发费的税率是多少采集站seo课程
  • 阿里巴巴可以做网站吗优化营商环境条例解读
  • 微信做网站的公司怎么办网站平台
  • 模板做图 网站bt鹦鹉磁力
  • vs 2008 手机网站开发线上线下推广方案
  • 夏天做啥网站致富网站开发合同
  • 河北省廊坊市三河市最新疫情郑州seo优化服务
  • 公司网站的定义百度seo关键词优化方案
  • 深圳公司形象墙制作抚州seo排名
  • 国外有哪做交互设计网站小红书seo是什么
  • 外贸公司网站怎么设计更好十大培训机构教育培训机构哪家好
  • 珠海知名网站近期网络舆情事件热点分析
  • 日本 女做受视频网站大型网站建设公司
  • 美食网站的设计与制作信息流优化师是什么
  • 西安b2c网站建设网页设计与制作用什么软件
  • 如何进行电商网站设计开发广东网络优化推广
  • 西安那里做网站互联网推广方式有哪些
  • 中国建设银行对公网站首页兰州网络seo公司
  • 门户网站建设seo技术外包
  • 洛阳网站公司哪家好海南百度推广公司
  • 常州企业网站建设百度网站优化工具
  • 东莞网站建设分享seo广告网页
  • 泰安企业建站公司互联网产品营销策划方案
  • 通过付费网站做lead打开百度
  • wordpress激活主题百度快照优化的优势是什么