设为首页 收藏本站
查看: 1282|回复: 0

[经验分享] 进一步认识golang中的并发

[复制链接]

尚未签到

发表于 2018-9-20 07:04:26 | 显示全部楼层 |阅读模式
  如果你成天与编程为伍,那么并发这个名词对你而言一定特别耳熟。需要并发的场景太多了,例如一个聊天程序,如果你想让这个聊天程序能够同时接收信息和发送信息,就一定会用到并发,无论那是什么样的并发。
  并发的意义就是:让一个程序同时做多件事情!
  理解这一点非常重要,是的,并发的目的只是为了能让程序同时做另一件事情而已,并发的目的并不是让程序运行的更快(如果是多核处理器,而且任务可以分成相互独立的部分,那么并发确实可以让事情解决的更快)。记得我学C++那时候开始接触并发,还以为每开一个线程程序就会加速一倍呢。。。。
  golang从语言级别上对并发提供了支持,而且在启动并发的方式上直接添加了语言级的关键字。我并不会很多语言,而且也没有很多的项目经验,可能从我嘴里说出的比较不会非常客观,但是起码和C/C++(不考虑C++11)利用系统API来操作线程的方式相比,golang的并发机制运用起来就非常舒适了,不必非要按照固定的格式来定义线程函数,也不必因为启动线程的时候只能给线程函数传递一个参数而烦恼。和Java相比的话,Go的优点就是并发的部分不必非得实现成一个class,而且更加轻量(其实我也不知道到底为什么更轻量^_^)。
  因为最近自己想写一个小开源项目,而且其中的关键部分会用到很多并发机制,于是开始重温习Go的并发相关的知识。从我学习Go到现在已经将近1年了,觉得现在再重新看Go的并发时收获颇多,因为毕竟写了不少Go的小程序,遇到过许多解释不通的现象和困惑,借着这次温故知新的机会,把学习来的新经验赶紧记录下来,分享给各位网友尤其是喜欢Go的朋友们。
  并发的启动
  这篇文章关于并发的启动我就一概而过了,如果要让一个函数并发运行,只需一个关键字"go":
[java] view plain copy  

  • func Afuntion(para1, para2, para3, ...) {
  •     // Do some process
  •     // ...
  • }

  • func main() {
  •     go Afuntion(para1, para2, para3, ...) //只需加一个go前缀,Afunction()就会并发运行
  • }
  go的并发启动非常简单,几乎没有什么额外的准备工作,要并发的函数和一般的函数没有什么区别,参数随意,启动的时候只需要加一个go关键之即可。
  当然,并发的启动没什么好讲的,并发最精髓的部分在于这些协程(协程类似于线程,但是是更轻量的线程)的调度
  我没法以一个资深的老专家向你全方位的讲解调度的各个方面,但是我可以把我遇到过的一些场景和我所用过的调度方法(所以绝对是能用的)分享给你。
  go提供了sync包channel机制来解决协程间的同步与通信。channel的用法非常灵活,使用的方式多种多样,而且官网的Effective Go中给出了channel的一种并发以外的方式。我们先来介绍sync包提供的调度支持吧。
  sync.WaitGroup
  sync包中的WaitGroup实现了一个类似任务队列的结构,你可以向队列中加入任务,任务完成后就把任务从队列中移除,如果队列中的任务没有全部完成,队列就会触发阻塞以阻止程序继续运行,具体用法参考如下代码:
[java] view plain copy  

  • // 代码粘上就可以跑通
  • package main

  • import (
  •     "fmt"
  •     "sync"
  • )

  • var waitgroup sync.WaitGroup

  • func Afunction(shownum int) {
  •     fmt.Println(shownum)
  •     waitgroup.Done() //任务完成,将任务队列中的任务数量-1,其实.Done就是.Add(-1)
  • }

  • func main() {
  •     for i := 0; i < 10; i++ {
  •         waitgroup.Add(1) //每创建一个goroutine,就把任务队列中任务的数量+1
  •         go Afunction(i)
  •     }
  •     waitgroup.Wait() //.Wait()这里会发生阻塞,直到队列中所有的任务结束就会解除阻塞
  • }
  我们可以利用sync.WaitGroup来满足这样的情况:
  ▲某个地方需要创建多个goroutine,并且一定要等它们都执行完毕后再继续执行接下来的操作。
  是的,WaitGroup最大的优点就是.Wait()可以阻塞到队列中的任务都完毕后才解除阻塞。
  channel
  channel是一种golang内置的类型,英语的直译为"通道",其实,它真的就是一根管道,而且是一个先进先出的数据结构。
  我们能对channel进行的操作只有4种:
  (1) 创建chennel (通过make()函数)
  (2) 放入数据 (通过 channel

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-597271-1-1.html 上篇帖子: golang thrift 总结一下网络上的一些坑 下篇帖子: mac上golang编译出现clang错误
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表