范文健康探索娱乐情感热点
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

面试官实现协程同步有哪些方式?

  为什么要做同步
  在进入正题前,我们先习惯性地摸着良心问问自(ji)己 (ji)  个 :为什么要做同步处理?
  假设现在有多个协程并发访问操作同一块内存中的数据,那么可能上一纳秒第一个协程刚把数据从寄存器拷贝到内存,第二个协程马上又把此数据用它修改的值给覆盖了,这样共享数据变量会乱套。
  举个栗子:package main  import(     "fmt"     "time" )  var share_cnt uint64 = 0  func incrShareCnt() {     for i:=0; i < 10000; i++ {         share_cnt++     } }  func main()  {      for i:=0; i < 2; i++ {         go incrShareCnt()     }      time.Sleep(10*time.Second)          fmt.Println(share_cnt) }
  上面代码用2个协程序并发各自增一个全局变量1000000 次,我们来看一下打印输出的结果:dashu@dashu > /data1/htdocs/go_practice > go run test.go 1014184 dashu@dashu > /data1/htdocs/go_practice > go run test.go 1026029 dashu@dashu > /data1/htdocs/go_practice > go run test.go 19630 ...
  从打印结果我们可以看到,虽然代码中我们对一个全局变量自增了20000次,但是没有一次打印输出20000的结果,原因就是因为协程间共享数据时发生了数据覆盖。实际上面的代码无聊sleep多就久都不会打印输出20000。协程同步方法
  那么,如何才能让数据在goroutine之间达到同步呢?下面跟大家分享以下三种数据同步的方式:time.Sleep channel sync.WaitGroup time.Sleep
  为什么sleep可以用来实现数据同步呢?我们看个栗子:func main()  {     go func() {         fmt.Println("goroutine1")     }()      go func() {         fmt.Println("goroutine2")     }() }
  执行上面那段代码你会发现没有任何输出,原因是:主协程在两个协程还没执行完就已经结束了,而主协程结束时会结束所有其他协程,  所以导致代码运行的结果什么都没有。
  我们在主协程结束前 sleep 一段时间就 可能出现  了结果:func main()  {     go func() {         fmt.Println("goroutine1")     }()      go func() {         fmt.Println("goroutine2")     }()      time.Sleep(time.Second) }
  打印输出:goroutine1 goroutine2
  为什么上面我要说 "可能会出现"  呢?上面代码中我们设置了睡眠时间为1s,由于协程的处理逻辑比较简单,所以能正常打印输出上面结果;如果我这两个协程里面执行了很复杂的逻辑操作(时间大于 1s),那么就会发现依旧也是无结果打印出来的。
  所以又一个问题来了:我们无法确定需要睡眠多久
  看来这sleep着实不靠谱,有没有什么办法来代替sleep呢?答案肯定是有的,我们来看第二种方法。channel(信道)
  channel是如何实现goroutine同步的呢?我们再看个典型的栗子:channel实现简单的生产者和消费者 package main  import (     "fmt"     "time" )  func producer(ch chan int, count int) {     for i := 1; i <= count; i++ {         fmt.Println("大妈做第", i, "个面包")         ch <- i                  // 睡眠一下,可以让整个生产消费看得更清晰点         time.Sleep(time.Second * time.Duration(1))     } }  func consumer(ch chan int, count int) {     for v := range ch {         fmt.Println("大叔吃了第", v, "个面包")         count--         if count == 0 {             fmt.Println("没面包了,大叔也饱了")             close(ch)         }     } }  func main() {     ch := make(chan int)     count := 5     go producer(ch, count)     consumer(ch, count) }
  上面代码中,我们另外起了个 goroutine 让大妈来生产5个面包(实际就是往channel中写数据),主 goroutine 让大叔不断吃面包(从channel中读数据)。我们来看一下输出结果:大妈做第 1 个面包 大叔吃了第 1 个面包 大妈做第 2 个面包 大叔吃了第 2 个面包 大妈做第 3 个面包 大叔吃了第 3 个面包 大妈做第 4 个面包 大叔吃了第 4 个面包 大妈做第 5 个面包 大叔吃了第 5 个面包 没面包了,大叔也饱了
  从输出结果我们可以看到,大妈一共做了5个面包,大叔一共吃了5个面包,同步上了!
  「Tip」 :
  上面代码,我们用 for-range 来读取 channel的数据,for-range 是一个很有特色的语句,有以下特点:如果 channel 已经被关闭,它还是会继续执行,直到所有值被取完,然后退出执行 如果通道没有关闭,但是channel没有可读取的数据,它则会阻塞在 range 这句位置,直到被唤醒。 如果 channel 是 nil,那么同样符合我们上面说的的原则,读取会被阻塞,也就是会一直阻塞在 range 位置。
  我们来验证一下,我们把上面代码中的 close(ch)  移到主协程中试试:package main  import (     "fmt"     "time" )  func producer(ch chan int, count int) {     for i := 1; i <= count; i++ {         fmt.Println("大妈做第", i, "个面包")         ch <- i                  // 睡眠一下,可以让整个生产消费看得更清晰点         time.Sleep(time.Second * time.Duration(1))     } }  func consumer(ch chan int, count int) {     for v := range ch {         fmt.Println("大叔吃了第", v, "个面包")         count--         if count == 0 {             fmt.Println("没面包了,大叔也饱了")         }     } }  func main() {     ch := make(chan int)     count := 5     go producer(ch, count)     consumer(ch, count)     close(ch) }
  打印输出:大妈做第 1 个面包 大叔吃了第 1 个面包 大妈做第 2 个面包 大叔吃了第 2 个面包 大妈做第 3 个面包 大叔吃了第 3 个面包 大妈做第 4 个面包 大叔吃了第 4 个面包 大妈做第 5 个面包 大叔吃了第 5 个面包 没面包了,大叔也饱了 fatal error: all goroutines are asleep - deadlock!  goroutine 1 [chan receive]: main.consumer(0xc00008c060, 0x0)  /data1/htdocs/go_project/src/github.com/cnyygj/go_practice/test.go:19 +0x5f main.main()  /data1/htdocs/go_project/src/github.com/cnyygj/go_practice/test.go:32 +0x7c exit status 2
  果然阻塞掉了,最终形成了死锁,抛出异常了。sync.WaitGroup
  如果你觉的上面两种方法还不过瘾,接下来我们再看个方法:sync.WaitGroup
  WaitGroup 内部实现了一个计数器,用来记录未完成的操作个数,它提供了三个方法:Add() 用来添加计数 Done() 用来在操作结束时调用,使计数减一  【我不会告诉你 Done() 方法的实现其实就是调用 Add(-1)】 Wait() 用来等待所有的操作结束,即计数变为 0,该函数会在计数不为 0 时等待,在计数为 0 时立即返回
  还是看栗子:func main()  {     var wg sync.WaitGroup     wg.Add(2) // 因为有两个动作,所以增加2个计数      go func() {         fmt.Println("Goroutine 1")         wg.Done() // 操作完成,减少一个计数     }()      go func() {         fmt.Println("Goroutine 2")         wg.Done() // 操作完成,减少一个计数     }()      wg.Wait() // 等待,直到计数为0  }
  打印输出:Goroutine 1 Goroutine 2
  以上就是今天要跟大家分享的内容,欢迎留言交流~

市场信心恢复中概股普涨,水滴上涨超14昨晚,中概股延续了反弹行情,美股三大股指期货全线上涨,纳指大涨近2。阿里滴滴均持续反弹,拼多多上涨12。53,腾讯音乐唯品会涨幅均超9,哔哩哔哩爱奇艺上涨幅度也超7。保险科技平台第我的程序员生涯结束了这是一篇迟到了很久的文章,事情还要从2018年我买房讲起。20182019年,是我自己无限接近结婚的一个阶段,想和自己五年恋爱长跑的女朋友组建一个新的家庭。现在住的这套房子就是在那杨澜,联想独立非执行董事,年薪235万。揭开面纱,还服气吗?5月15日下午,联想集团在港交所发布公告称,委任电视节目主持人传媒企业家杨澜为公司独立非执行董事,年薪33万美元,折合人民币约为235万元。该任命即日起生效。委任电视节目主持人传媒京东,全国开药店了!三天又增两家京东宣布在云南北海分别成立药房子公司,西南地区布局再添一笔。截至目前,京东大药房在全国25个省市已设立43家药房子公司(文末附完整名单)。三天宣布新增两家药房子公司今天,赛柏蓝药店说说音响线材繁多的样式特点各类线材的种类选用和声音特点对于电源线,在车载音响上,不必要过分追求铜材的纯度,线径够粗才是硬道理。个人认为,6号线属于入门级,适合单台或2台功率在50W路的功放使用。4号线属于正说说高音喇叭繁多的样式特点高音在一首歌曲里面,或是一段乐曲里面,肯定是最抓耳的,高音一出马上就能激发听者的情绪,在音乐会上也是最能带动观众情绪的。那对音箱来说,配什么样的高音单元才是最好的呢?我们从高音单元带着比特币起飞在拉美用加密货币坐飞机成为可能据智利美洲经济网站报道,在拉美,使用加密货币支付私人飞行成为可能。总部位于哥伦比亚的私人航空公司Flapz在11月初宣布,它将开始接受使用加密货币来预订商务航班和相关产品。该航空公中国快递年业务量首次突破1000亿件映射中国速度与中国活力来源人民网原创稿人民网北京12月8日电(记者李楠桦)12月8日,国家邮政局快递大数据平台实时监测数据显示,2021年我国快递业务量已达1000亿件,标志着我国邮政快递业发展又迈上了曲线救国解决5G芯片,华为终于还是把手机业务外包了不知道最近大家有没有看到一则新闻,今年10月份,苹果因为发布了iPhone13系列手机,在中国市场的销量环比增长46,时隔6年再次成为最大的智能手机厂商。而且从具体数据来看,10月多线程的实际应用场景,有返回值的处理业务场景我们公司做的是加油业务,用户可以在app上通过当前位置和目标位置来查询地图路线以及路线途径的所有加油站,路线查询会调用高德地图提供的接口,途径油站则根据返回的路线信息进行查阿里市值蒸发3。3万亿,高管离职动荡不已,已无力与腾讯争雄?众所周知,中国互联网的双雄是阿里和腾讯,两家虽然在各自的主导领域发展,但仍然有很多业务重合,所以竞争从未停止过。在过去一段时间以来,阿里无论是市值,还是营收,似乎都要领先腾讯一些。
1199元起,5000mAh8GB128GB,荣耀新款5G手机价格亲民荣耀已经独立一年多时间了,为了满足发展的需要,独立之后的荣耀,也搞起了机海战术,推出了不同定位的产品,尽管已经脱离了华为,但产品或多或少还有一些华为元素,加上在配置方面也比较用心,我们禁用谷歌太明智了,要不然被曝光军事基地的,可能就是我们了2022年4月18日,乌克兰发表声明表示谷歌地图将以最大分辨率为乌克兰提供俄罗斯境内军事基地军事行动部署卫星图片。这么看来,我国禁用谷歌反而是明智之举,如果不禁用,说不定哪一天受威盖尔德纳奖得主约翰迪克思考一个更大的问题,然后去回答2022年盖尔德纳奖得主约翰迪克(JohnDick)导读素有小诺贝尔奖美誉的盖尔德纳奖于今年4月颁布,在今年的获奖者中,一位名叫约翰迪克的科学家引人侧目。约翰迪克博士是首次在急性髓专家寻求中国互联网的外王之道当前,中国互联网迈入了大航海时代。在出海热潮下,中国互联网企业何以实现大浪淘金?近日,中国社科院经济所研究员社科院大学教授王宏淼发表文章,以电商出海游戏出海移动支付出海为例,阐释中腾讯起诉国产手机巨头,发生了什么?本文原创,禁止搬运和抄袭,违者必究!腾讯产品生态遍布互联网的各个角落,在各大互联网产业领域都能看见腾讯的身影。要么是腾讯直接参与的布局,要么是通过投资的方式成为幕后大佬。而为了让生美媒在这一领域,印度和中国不能挂断对方的电话美国华尔街日报中文网5月17日文章,原题印度不能挂断中国智能手机的电话印度正在调查中国智能手机制造商小米在印度的子公司。小米已向印度法院提起诉讼,指控印度打击金融犯罪的政府部门使用4月交付5074台,品牌成交均价突破43万,蔚来能否坐稳高端市场头部?根据乘联会数据,2022年新能源乘用车销量预计为550万辆,整体新能源汽车销量预期为600万辆。而从2021年的新能源汽车数据来看,112月新能源乘用车批发331。2万辆,112月苹果公布iOS16细节,门检测AppleWatch镜像实时字幕今年的5月19日是第11个全球无障碍宣传日,就在前两天,苹果也公布了一系列新的iOS16功能,这次是辅助功能,面向iPhone和AppleWatch用户,这些用户是耳聋听力困难失明弹性边界附近空化泡迁移和周期特性试验研究摘要抗空蚀材料的应用极大提高了泄水建筑物的过流性能和使用寿命,是减轻空蚀破坏最有效途径之一。针对目前关于弹性材料抗空蚀特性的机理研究尚有欠缺的问题,为了研究弹性材料如何减免空蚀破坏免费生成HTTPS证书方法一安装acme。sh普通用户和root用户都可以安装使用。会安装在。acme。sh目录下,以后生成的证书也会在这里面,按照域名为文件夹安置。acme。sh的中文说明有详细介绍cur高校副院长在工作群发色情言论,被停职前,都有什么奇事发生?5月19日,网爆郑州轻工业大学体育学院副院长谭某某工作群发色情言论。谭某某随后解释称,微信号被盗,刚通过警方找回来了。20日,体育学院党政办主任回应称,谭某某微信号确实被盗,正在补