在Go中使用并发例程打印问题

时间:2011-12-02 11:40:46

标签: go concurrency goroutine

我有三个这样的并发例程,

func Routine1() {

Print (value a, value b, value c)
Print (value a, value b, value c)
Print (value a, value b, value c)

}

func Routine2() {
Print (value e, value f, value g)
Print (value e, value f, value g)
Print (value e, value f, value g)
}
func Routine3() {
Print (value x, value y, value z)
Print (value x, value y, value z)
Print (value x, value y, value z)
}

func main() {
go Routine1(command12, response12, command13, response13)
go Routine2(command12, response12, command23, response23)
Routine3(command13, response13, command23, response23)
}

现在我面临的问题是,有时会发生这样的情况,由于三个并发例程的结果,有时print语句没有正确执行意味着不打印整体,有一些东西被另一个打印插入。例如,例程1的Print(值a,值b,值c)给出输出,如值a,值b,值g,其中值g由例程2插入。任何人都可以建议我,我该如何阻止它?我尝试过sync-mutex程序。但是可能是因为我的代码太长而且我可能无法以正确的方式解锁 - 因此它会给出死锁错误。任何人都可以建议我如何以简单的方式或风险较低的sync-mutex程序实现这些。

有关我的这个问题的更多信息可以找到here

1 个答案:

答案 0 :(得分:6)

按照您的描述进行打印不是原子操作。不要使用互斥锁,请尝试使用Go方式。将通道传递到每个接受字符串的goroutine。每次要打印时,只需将字符串发送到该频道即可。

单独的goroutine只会从该频道读取并打印出来的任何内容。这样就不需要锁了。

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    wg.Add(2) // 2 routines we need to wait for.

    stdout := make(chan string)

    go routine1(&wg, stdout)
    go routine2(&wg, stdout)
    go printfunc(stdout)

    wg.Wait()

    close(stdout)
}

func routine1(wg *sync.WaitGroup, stdout chan<- string) {
    defer wg.Done()

    stdout <- "first print from 1"
    // do stuff
    stdout <- "second print from 1"
}

func routine2(wg *sync.WaitGroup, stdout chan<- string) {
    defer wg.Done()

    stdout <- "first print from 2"
    // do stuff
    stdout <- "second print from 2"
}

func printfunc(stdout <-chan string) {
    for {
        select {
        case str := <- stdout:
            fmt.Println(str)
        }
    }
}