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

Go并发编程指南第一篇

  竞争条件和数据竞争
  当两个或多个操作必须以正确的顺序执行时,就会出现竞争条件,但程序尚未编写为保证维护此顺序。
  数据竞争是指一个并发操作试图读取一个变量,而在某个不确定的时间另一个并发操作试图写入同一个变量。main func 是主 goroutine。 func main() {     var data int     go func() {         data++     }()      if data == 0 {         fmt.Printf("the value is %d", data)     } }sync内存访问同步
  sync 包包含对低级内存访问同步最有用的并发原语。临界区是代码中可以访问共享内存的地方mutex互斥体
  Mutex 代表"互斥",是一种保护程序关键部分的方法。 type Counter struct {     mu sync.Mutex     value int }  func (c *Counter) Increment() {     c.mu.Lock()     defer c.mu.Unlock()     c.value++ }waitgroup等待组
  调用添加一组goroutines var wg sync.WaitGroup for _, salutation := range []string{"hello", "greetings", "good day"} {     wg.Add(1)     go func(salutation string) {          defer wg.Done()         fmt.Println(salutation)     }(salutation)  } wg.Wait()读写互斥锁
  更细粒度的内存控制,可以请求只读锁 producer := func(wg *sync.WaitGroup, l sync.Locker) {      defer wg.Done()     for i := 5; i > 0; i-- {         l.Lock()         l.Unlock()         time.Sleep(1)      } }  observer := func(wg *sync.WaitGroup, l sync.Locker) {     defer wg.Done()     l.Lock()     defer l.Unlock() }  test := func(count int, mutex, rwMutex sync.Locker) time.Duration {     var wg sync.WaitGroup     wg.Add(count+1)     beginTestTime := time.Now()     go producer(&wg, mutex)     for i := count; i > 0; i-- {         go observer(&wg, rwMutex)     }      wg.Wait()     return time.Since(beginTestTime) }  tw := tabwriter.NewWriter(os.Stdout, 0, 1, 2, " ", 0) defer tw.Flush()  var m sync.RWMutex fmt.Fprintf(tw, "Readers	RWMutex	Mutex ")  for i := 0; i < 20; i++ {     count := int(math.Pow(2, float64(i)))     fmt.Fprintf(         tw,         "%d	%v	%v ",         count,         test(count, &m, m.RLocker()),         test(count, &m, &m),     ) }cond条件
  如果有某种方法可以让 goroutine 有效地休眠,直到收到唤醒并检查其状态的信号,那就更好了。这正是 Cond 类型为我们所做的。
  Cond 和 Broadcast 是用于通知在 Wait 调用中阻塞的 goroutines 条件已被触发的方法。 type Button struct {     Clicked *sync.Cond }  func main() {     button := Button{         Clicked: sync.NewCond(&sync.Mutex{}),     }      // running on goroutine every function that passed/registered     // and wait, not exit until that goroutine is confirmed to be running     subscribe := func(c *sync.Cond, param string, fn func(s string)) {         var goroutineRunning sync.WaitGroup         goroutineRunning.Add(1)          go func(p string) {             goroutineRunning.Done()             c.L.Lock() // critical section             defer c.L.Unlock()              fmt.Println("Registered and wait ... ")             c.Wait()              fn(p)         }(param)          goroutineRunning.Wait()     }      var clickRegistered sync.WaitGroup      for _, v := range []string{         "Maximizing window.",         "Displaying annoying dialog box!",         "Mouse clicked."} {          clickRegistered.Add(1)          subscribe(button.Clicked, v, func(s string) {             fmt.Println(s)             clickRegistered.Done()         })     }      button.Clicked.Broadcast()      clickRegistered.Wait() }Once
  确保即使在多个 goroutine 之间也只执行一次 var count int  increment := func() {     count++ }  var once sync.Once  var increments sync.WaitGroup increments.Add(100)  for i := 0; i < 100; i++ {     go func() {         defer increments.Done()         once.Do(increment)     }() }  increments.Wait() fmt.Printf("Count is %d ", count)Pool
  管理连接池,数量 package main  import (     "fmt"     "sync" )  func main() {     myPool := &sync.Pool{         New: func() interface{} {             fmt.Println("Creating new instance.")              return struct{}{}         },     }      // Get call New function defined in pool if there is no instance started     myPool.Get()     instance := myPool.Get()     fmt.Println("instance", instance)      // here we put a previously retrieved instance back into the pool,      // this increases the number of instances available to one     myPool.Put(instance)      // when this call is executed, we will reuse the      // previously allocated instance and put it back in the pool     myPool.Get()      var numCalcsCreated int     calcPool := &sync.Pool{         New: func() interface{} {             fmt.Println("new calc pool")              numCalcsCreated += 1             mem := make([]byte, 1024)              return &mem         },     }      fmt.Println("calcPool.New", calcPool.New())      calcPool.Put(calcPool.New())     calcPool.Put(calcPool.New())     calcPool.Put(calcPool.New())     calcPool.Put(calcPool.New())      calcPool.Get()      const numWorkers = 1024 * 1024     var wg sync.WaitGroup     wg.Add(numWorkers)      for i := numWorkers; i > 0; i-- {         go func() {             defer wg.Done()              mem := calcPool.Get().(*[]byte)             defer calcPool.Put(mem)              // Assume something interesting, but quick is being done with             // this memory.         }()     }      wg.Wait()     fmt.Printf("%d calculators were created.", numCalcsCreated) }死锁
  死锁是其中所有并发进程都在等待彼此。 package main  import (     "fmt"     "sync"     "time" )  type value struct {     mu    sync.Mutex     value int }  func main() {     var wg sync.WaitGroup     printSum := func(v1, v2 *value) {         defer wg.Done()         v1.mu.Lock()         defer v1.mu.Unlock()          // deadlock         time.Sleep(2 * time.Second)         v2.mu.Lock()         defer v2.mu.Unlock()          fmt.Printf("sum=%v ", v1.value+v2.value)     }      var a, b value     wg.Add(2)     go printSum(&a, &b)     go printSum(&b, &a)      wg.Wait() }
  总结
  本文是go语言并发编程指南最佳实践第一篇,后续第二篇还会整理各种channel的特性,锁的使用在并发编程中的特点与各种用途举例,全部都是最接地气的代码示例。关注我,敬请期待下一篇。

在使用了将近2年纯电动后,我认为电动车确实很香,适合家用这次咱们不说废话,谈谈油车与电车,作为油电双车的车主,并且作为一个普通的上班族,在使用了一年多电车以及油车之后,我认为电动车的优势是非常明显的,如果只是购买一台城市用车的话,电动车泰国2023年首月工业信心指数达43个月以来最高水平2月23日,据泰媒报道称,泰国总理府办公室发言人阿努查透露,泰国工业联合会(FTI)就工业信心方面对45个行业共计1,321名从业者进行调查,发现工业信心指数由2022年12月的9河南不断提升产业基础能力,加快推进高水平对外开放改革破局,迎难而上拼经济核心阅读近年来,河南发挥自身优势,初步形成以先进制造业和现代服务业为主体特色现代农业为基础的现代产业体系。当前,河南正着力建设制造业强省农业强省,加快推进高水平对外开放,打造具有国人民币兑美元中间价报6。9028,调贬269个基点中国外汇交易中心数据显示,2月23日,人民币兑美元中间价报6。9028,调贬269个基点。前一交易日中间价报6。8759,在岸人民币1630收盘价报6。8953,夜盘收报6。891甩开巨头ZARA,国内跨境电商拟冲击IPO中国企业出海一直备受关注,其间囊括全球资本流动中国企业的全球竞争力中国制造的实力海外营商环境和政策变化等众多重要话题,甚至涉及到中国文化输出中外文化隔阂等意识形态层面的议题。虽然全托育行业的这三笔账,要怎么算?台州市路桥区小鹤培家庭托育点里,保育员正和小朋友玩游戏。受访者供图我俩都上班,又没老人带,去托班省心。宝宝不到一周岁,放托儿所怎么放心?设施和师资都行,就是下午5点要接,太早了。浙白酒概念板块跌0。73武商集团涨5。37居首来源中国经济网中国经济网北京2月23日讯今日,白酒概念板块整体涨幅0。73,其中11只股票上涨,1只股票平盘,35只股票下跌。数据显示,截至今日,白酒概念板块近一周涨幅1。40,近金色螳川春日赏花经济热春日的安宁市温泉街道牧羊湖景区,沿螳螂川两岸分布的万亩油菜花陆续绽放,盛开成一片金色的海洋。市民游客们沿着河流,穿梭于阡陌之上,徜徉在花海之间,漫步骑马蹬观光自行车,五彩花田展开了穿越新概念雾霾,探寻数字化共识之路编者按数字化技术的本质作用是重构人和机器的关系,但工业企业的数字化转型却是知易行难。知行合一的关键,是要把技术可行性与经济可行性统一起来。为此,需要深入理解现代工业的本质特征和技术库克真大方!iPhone13直降1800元,入手256GB版本更划算买新不买旧是多数消费者的一贯实现,随着智能手机市场纷争的不断加剧,很显然这个理念已完全不适用,纵观是新发布的产品还是去年的产品甚至于说是前年的产品,就普通消费者日常使用的话,仍旧完DarmosharkM3轻量无线游戏鼠标评测轻量机身,强悍性能Darmoshark作为新晋的国内外设品牌,凭借旗下创新设计的游戏鼠标在外设玩家群体中有着较高的关注度与良好的口碑。随着轻量化无线游戏鼠标在玩家群体中的关注度越来越高,Darmos
哈萨克斯坦总理国民期待政府带来切实变化哈萨克斯坦政府总理斯迈洛夫14日上午主持召开了政府工作会议。会议就有效落实12月12日的政府扩大会议期间托卡耶夫总统下达的各项指示的相关举措进行了讨论和安排。斯迈洛夫在会上指出,今民族服饰变装热潮在包容多元中秀出文化自信刘柏薇(重庆大学)近日,在短视频平台上刮起了一阵民族服饰变装热潮,网友们跟着卡点音乐,抬手落手间完成从常服到民族传统服饰的转变。洗脑的音乐,华丽的服饰,米姆式的传播,民族服饰之美民24岁的神龟姆巴佩身价12亿,3段姐弟恋,绯闻女友是变性人姆巴佩进了两个球,多亏了他的天赋,如果这几个球处理得更理智,而不是被草草扫地出门,如果他输球或错过,他将立即成为新的足坛第一。当黄健翔有点激动地发文的时候,球迷与娱乐都同时将眼睛移大战在即!20000名摩洛哥球迷来了据葡萄牙新闻日报报道,卡塔尔世界杯14决赛摩洛哥队与葡萄牙队的比赛现场,将有超过10000名警察被调动参加安保工作,在本届世界杯乃至其他任何一届世界杯都从未见过这样的事情。摩洛哥球明晨3时,世界杯14决赛法国男足死磕英格兰,高卢雄鸡PK三狮军团明晨3时,世界杯14决赛法国男足死磕英格兰,高卢雄鸡PK三狮军团!北京时间12月11日凌晨3时,央视体育频道CCTV5央视奥林匹克频道CCTV16上海五星体育和广东体育等平台同时直世界杯决赛倒计时!用什么观战更舒服?大屏120Hz很重要本届世界杯由于在北半球冬季举行,最近这一个月,也着实让国内广大球迷们在年底前兴奋了一把。最近这几天,世界杯进入到了四分之一决赛期间,各支强队实力尽出,巴西克罗地亚荷兰阿根廷的两场点又一个第一次!武汉三镇锁定亚冠名额长江日报大武汉客户端12月10日讯(记者马万勇)在今天下午结束的2022年中超联赛第30轮较量中,成都蓉城主场与上海海港00战平,以55分位居积分榜第4位。这也意味着在联赛还剩4轮李铁为什么不重用归化球员大家都清楚,中国足球踢不进世界杯的主要原因是球员水平太菜,特别是锋线球员在面对球门时慌得一逼,总是不停地倒脚,调整,等你忙乎完了,守门员都上来封堵你了,结果不是射在人家身上,就是打代表韩国参加世界杯的孙准浩,估计赶上泰山队最后三场中超扬子晚报网12月10日讯(记者张晨瑆孙云岳张昊)北京时间12月9日晚,在中超第30轮的天王山之战中,武汉三镇和山东泰山两支争冠球队打成11,武汉三镇队多赛一场仍领先3分。泰山队主力网友热议新疆自驾托运回来,托运费用原来这么实惠自驾去新疆,沿途欣赏祖国大好山水,玩上个两三周,再把车运回来。有车主表示实在是太便利了!新疆地域广袤,从内地到新疆的路途大约是3000到5500km,在正常车型下,托运费用在3k5广西警察学院,上演警服时装秀,网友把笑场的那个打30大板导语大学阶段可以说是每一个学生都非常向往的阶段,初高中学生们学习比较辛苦,基本上可以说没有什么业余活动,都在为了走进理想的大学而努力和学习。虽然大学阶段也要学习,但是学生们学业压力