Go例程中的有限循环

时间:2017-11-13 05:59:57

标签: go

在完成主题

后,我试图同步执行两个或更多的例行程序

goroutines order of execution

我写了一些代码来测试go例程的行为 (我把它看作一个队列,顺便说一下,并发教程页面并没有真正帮助我)

package main

import (
        "fmt"
        "sync"
)

const size = 10
var vChan chan int = make(chan int, size)

func justSend(wg *sync.WaitGroup) {
        defer wg.Done()
        for i := 1; i <= 10; i++ {
                vChan <- i
        }
}

func justPrint(wg *sync.WaitGroup) {
        defer wg.Done()
        v := <- vChan
        fmt.Printf("%4d ", v);
}

func main() {
        wg := new(sync.WaitGroup)

        go func() {
                wg.Add(1)
                go justSend(wg)
                wg.Wait()
                wg.Add(size)
                go justPrint(wg)
                wg.Wait()
                close(vChan)
        }()
}

但它没有打印,如果我们设计一个go例程总是在那里有一个无限循环或者我们不能让它正常工作?

(这段代码是为我构建多个websocket连接并测试我们的API服务器响应的真正问题而准备的,所以...我认为在不同的函数之间传递一堆相同类型的通道非常烦人,所以我设置了全球)

2 个答案:

答案 0 :(得分:5)

不,不要使用无限循环。 使用渠道或同步包的功能可以更好地完成同步。 main()也是 goroutine (主要的),所以如果main在其他goroutines之前退出,你的任务仍未完成。 一种方法是使用sync.WaitGroup等待其他goroutine完成(参见示例1,2和3)。另一种方法是使用通道等待其他goroutine完成(参见示例4和5)。我提供了一些示例,以便您可以选择适合您的案例:

1-一个tx和多个rx(保持频道开放),请尝试this

package main

import (
    "fmt"
    "sync"
)

func main() {
    go tx()
    wg.Add(20)
    for i := 1; i <= 20; i++ {
        go rx()
    }
    wg.Wait()
}

func tx() {
    for i := 1; i <= 20; i++ {
        vChan <- i
    }
}

func rx() {
    defer wg.Done()
    fmt.Println(<-vChan)
}

var wg sync.WaitGroup

var vChan = make(chan int, 10)

2-一个tx和一个rx(保持频道开放),尝试this

package main

import (
    "fmt"
    "sync"
)

func main() {
    go tx()
    wg.Add(1)
    go rx()
    wg.Wait()
}

func tx() {
    for i := 1; i <= 20; i++ {
        vChan <- i
    }
}

func rx() {
    defer wg.Done()
    for i := 1; i <= 20; i++ {
        fmt.Println(<-vChan)
    }
}

var wg sync.WaitGroup

var vChan = make(chan int, 10)

3-关闭通道以发信号通知tx结束,尝试this

package main

import (
    "fmt"
    "sync"
)

func main() {
    go tx()
    wg.Add(1)
    go rx()
    wg.Wait()
}

func tx() {
    for i := 1; i <= 5; i++ {
        vChan <- i
    }
    close(vChan)
}

func rx() {
    defer wg.Done()
    for v := range vChan {
        fmt.Println(v)
    }
}

var wg sync.WaitGroup

var vChan = make(chan int, 10)

4-关闭通道以发信号通知tx结束,使用主goroutine为rx,尝试this

package main

import (
    "fmt"
)

func main() {
    go tx()
    for v := range vChan {
        fmt.Println(v)
    }
}

func tx() {
    for i := 1; i <= 20; i++ {
        vChan <- i
    }
    close(vChan)
}

var vChan = make(chan int, 10)

5-使用退出频道,尝试this

package main

import (
    "fmt"
)

func main() {
    go tx()
    go rx()
    <-quit
}
func rx() {
    for v := range vChan {
        fmt.Println(v)
    }
    quit <- struct{}{}
}
func tx() {
    for i := 10; i <= 15; i++ {
        vChan <- i
    }
    close(vChan)
}

var quit = make(chan struct{}, 1)
var vChan = make(chan int, 10)

输出:

10
11
12
13
14
15

6- Multi tx multi rx,试试this

package main

import (
    "fmt"
    "sync"
)

func main() {
    wg.Add(5)
    for i := 1; i <= 5; i++ {
        go tx()
        go rx()
    }
    wg.Wait()
}

var n = 10

func tx() {
    vChan <- n
    n++
}

func rx() {
    defer wg.Done()
    fmt.Println(<-vChan)
}

var wg sync.WaitGroup

var vChan = make(chan int, 10)

7-多个tx和一个rx,尝试this

package main

import (
    "fmt"
    "sync"
)

func main() {
    for i := 1; i <= 5; i++ {
        wg.Add(1)
        go tx()
    }

    go rx()
    wg.Wait()
}

func rx() {
    for {
        fmt.Println(<-vChan)
        wg.Done()
    }
}

var n = 20

func tx() {
    vChan <- n
    n++
}

var wg sync.WaitGroup

var vChan = make(chan int, 10)

我希望这会有所帮助。

答案 1 :(得分:0)

You have put goroutine in main and main function finishes before your go routine finishes. So either do not use goroutine in main or use some kind of boolean receiving channel at the end of main which gets true when goroutine completed.