golang

golang sync.WaitGroup 用法

吃可爱长大的小学妹 提交于 2019-12-04 23:42:07
执行一个简单协程 package main import ( "fmt" "time" ) func main ( ) { for i := 0 ; i < 100 ; i ++ { go fmt . Println ( i ) } time . Sleep ( time . Second ) } 分析: 为什么会有sleep 呢, 主线程为了等待goroutine都运行完毕, 不得不在程序的末尾使用time.Sleep()来睡眠一段时间, 等待 其他线程充分运行 。对于简单的代码100 个for 循环可以在1秒内运行完但是实际的场景中大部分是1秒不够的, 而且大部分的时间 我们都无法预测for 循环内的代码运行时间的长短, 这个时候就不能使用time.sleep() 来完成等待操作了。 使用管道来 完成 操作 func main ( ) { c := make ( chan bool , 100 ) for i := 0 ; i < 100 ; i ++ { go func ( i int ) { fmt . Println ( i ) c <- true } ( i ) } for i := 0 ; i < 100 ; i ++ { <- c } } 通道是可以完全达到目的的 但是在这里 管道会 有些大材小用,因为它被设计出来不仅仅只是在这里用作简单的同步处理

Golang的sync.WaitGroup陷阱

故事扮演 提交于 2019-12-04 23:41:38
sync.WaitGroup 是并发环境中,一个相当常用的数据结构,用来等待所有协程的结束,在写代码的时候都是按着例子的样子写的,也没用深究过它的使用。前几日想着能不能在协程中执行 Add() 函数,答案是不能,这里介绍下。 陷阱在WaitGroup的3个函数的调用顺序上。先回顾下3个函数的功能: Add(delta int) :给计数器增加delta,比如启动1个协程就增加1。 Done() :协程退出前执行,把计数器减1。 Wait() :阻塞等待计数器为0。 考一考 下面的程序是创建了协程father,然后father协程创建了10个子协程,main函数等待所有协程结束后退出,看看下面代码有没有什么问题? package main import ( "fmt" "sync" ) func father ( wg * sync . WaitGroup ) { wg . Add ( 1 ) defer wg . Done ( ) fmt . Printf ( "father\n" ) for i := 0 ; i < 10 ; i ++ { go child ( wg , i ) } } func child ( wg * sync . WaitGroup , id int ) { wg . Add ( 1 ) defer wg . Done ( ) fmt . Printf (

GOLANG sync.WaitGroup讲解

坚强是说给别人听的谎言 提交于 2019-12-04 23:41:24
Package sync type WaitGroup A WaitGroup waits for a collection of goroutines to finish. The main goroutine calls Add to set the number of goroutines to wait for. Then each of the goroutines runs and calls Done when finished. At the same time, Wait can be used to block until all goroutines have finished. A WaitGroup must not be copied after first use. type WaitGroup struct { // contains filtered or unexported fields } func (*WaitGroup) Add func (wg * WaitGroup ) Add(delta int ) Add adds delta(增量), which may be negative, to the WaitGroup counter. If the counter becomes zero, all goroutines

Golang::WaitGroup 等待所有goroutine退出

社会主义新天地 提交于 2019-12-04 23:40:46
简介 waitgroup类似于的信号量,用于等待所有的goroutine退出,基本的操作包括 add(int) 增加信号的值,add的参数应该都为正数 ,done() 减少信号的值,相当于add(-1) ,wait() 等待信号量值为0,等待期间会一直阻塞 code package main import ( "fmt" "sync" "time" ) var waitGroutp = sync .WaitGroup {} func goroutine1() { time .Sleep (time .Second * 3 ) waitGroutp .Done () fmt .Println ( "goroutine1退出" ) } func goroutine2() { time .Sleep (time .Second * 8 ) waitGroutp .Done () fmt .Println ( "goroutine2退出" ) } func goroutine3() { time .Sleep (time .Second * 1 ) waitGroutp .Done () fmt .Println ( "goroutine3退出" ) } func goroutine4() { time .Sleep (time .Second * 2 ) waitGroutp .Done

Golang中WaitGroup使用的一点坑

点点圈 提交于 2019-12-04 23:39:34
Golang中WaitGroup使用的一点坑 Golang 中的 WaitGroup 一直是同步 goroutine 的推荐实践。自己用了两年多也没遇到过什么问题。直到一天午睡后,同事扔过来一段奇怪的代码: 坑1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package main import ( "log" "sync" ) func main ( ) { wg : = sync . WaitGroup { } for i : = 0 ; i & lt ; 5 ; i ++ { go func ( wg sync . WaitGroup , i int ) { wg . Add ( 1 ) log . Printf ( "i:%d" , i ) wg . Done ( ) } ( wg , i ) } wg . Wait ( ) log . Println ( "exit" ) } 撇了一眼,觉得没什么问题。然而,它的运行结果是这样: 1 2 3 2016 / 11 / 27 15 : 12 : 36 exit [ Finished in 0.7s ] 或这样: 1 2 3 4 2016 / 11 / 27 15 : 21 : 51 i : 2 2016 / 11 / 27 15 : 21

golang线程同步WaitGroup简介

你说的曾经没有我的故事 提交于 2019-12-04 23:38:51
WaitGroup用于线程同步,WaitGroup等待一组线程集合完成,才会继续向下执行。 主线程(goroutine)调用Add来设置等待的线程(goroutine)数量。 然后每个线程(goroutine)运行,并在完成后调用Done。 同时,Wait用来阻塞,直到所有线程(goroutine)完成才会向下执行。 对官方的代码做简单修改: package main import ( "fmt" "sync" ) func main() { var wg sync.WaitGroup var urls = []string{ "http://www.golang.org/", "http://www.google.com/", "http://www.somestupidname.com/", } for _, url := range urls { // Increment the WaitGroup counter. wg.Add(1) go func(url string) { // Launch a goroutine to fetch the URL. defer wg.Done() // Fetch the URL. fmt.Println(url) }(url) } // Wait for all goroutines to finish. wg.Wait()

golang 中sync.WaitGroup以及select简单实用

偶尔善良 提交于 2019-12-04 23:38:03
golang中sync.WaitGroup的作用类似于channel,可实现并发。 package main import ( "fmt" "runtime" "sync" ) func main() { runtime.GOMAXPROCS(runtime.NumCPU()) //多核 wg := sync.WaitGroup{} wg.Add(10) for i := 0; i < 10; i++ { go f(&wg, i) } wg.Wait() } func f(w *sync.WaitGroup, i int) { fmt.Println(i, "go") w.Done() } golang中select是配合channel使用的。 package main import ( "fmt" "runtime" ) func main() { runtime.GOMAXPROCS(runtime.NumCPU()) c1, c2 := make(chan int), make(chan string) flag := make(chan bool, 2) go func() { for { select { case k, err := <-c1: if !err { flag <- true break } fmt.Println(k) case k, err := <

Golang 中使用WaitGroup的那点坑

吃可爱长大的小学妹 提交于 2019-12-04 23:36:08
sync.WaitGroup对于Golang开发者来说并不陌生,其经常作为多协程之间同步的一种机制。用好它势必会让你事半功倍,但是一旦错用将引发问题。关于WaitGroup的使用网上有很多例子,在此就不做介绍了,我想说的是我在项目中使用WaitGroup遇到的坑。 在项目中,因为服务器有同步需求, 所以直接使用了WaitGroup,但是未考虑使用场景,结果在项目上线之后,高峰期的时候客户端经常出现卡顿,经过多方查找,才发现如果使用WaitGroup的时候,未启动单独的goroutine,那么极有可能造成主线程的阻塞,所以我做了下面的测试(测试中,我把WaitGroup置于协程内): func main() { fmt.Println("main-1") testchan() fmt.Println("main-2") } func testchan() { fmt.Println("testchan-1") go func() { var wg *sync.WaitGroup = new(sync.WaitGroup) fmt.Println("testchan-2") testchan1(wg) fmt.Println("testchan-5") wg.Wait() time.Sleep(time.Duration(5) * time.Second) fmt.Println(

Golang sync.WaitGroup 简介与用法

瘦欲@ 提交于 2019-12-04 23:35:52
1.简介 sync.WaitGroup 用于阻塞等待一组 Go 程的结束。主 Go 程调用 Add() 来设置等待的 Go 程数,然后该组中的每个 Go 程都需要在运行结束时调用 Done(), 递减 WaitGroup 的 Go 程计数器 counter。当 counter 变为 0 时,主 Go 程被唤醒继续执行。 type WaitGroup struct { // contains filtered or unexported fields } //设置需要等待的 Go 程数量 func (wg *WaitGroup) Add(delta int) //Go 程计数器减 1 func (wg *WaitGroup) Done() //阻塞等待所有 Go 程结束(等待 Go 程计数器变为 0) func (wg *WaitGroup) Wait() WaitGroup 有三个方法,其中 Done() 调用了 Add(-1)。标准用法: (1)启动 Go 程时调用 Add(); (2)在 Go 程结束时调用 Done(); (3)最后调用 Wait()。 2.使用示例 package main import ( "fmt" "sync" "time" ) var wg sync.WaitGroup func foo1() { defer wg.Done() fmt

go学习笔记0-helloWorld

蹲街弑〆低调 提交于 2019-12-04 23:32:53
有一次听一个沙龙技术演讲,讲师说go是互联网时代的c,听了详细介绍以后感觉很赞,尤其是并行层面真正在语言层面上做了控制及特殊的内存管理机制等。。。 好吧,下面上先上helloWorld代码。(以后系列的博客也是以代码为主) package main //这个是必须的,所有的go文件必须以 package开头 import "fmt" // ”fmt“是go必须要引入格式化I/O的库。如果要引入多个库import用( )号包裹所有的库。例如 import ( “fmt” “strconv”) func main() { //这是主函数 fmt.Printf("hello world!")// fmt的Print()函数用于打印 } 这是最简单的一个go程序。 关于go程序的编译跟执行笔者是再win7 64bit机器用的LiteIDE工具,LiteIDE是由国人开发的一款go编译执行开发环境,用起来感觉挺不错的。第一次编译执行go程序需要配置工具的LiteEnv(主要是配置golang下载解压后的目录) 下面说一下go的一些变量定义: go语言与其他语言不通的地方就是在变量类型放在变量后边 如下: var i int; var j bool; 给i跟j赋值 i=10; j=true; 如果要定义很多变量会需要些 var,go也可以这样定义变量 如下: var( i int j bool