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

huangapple go评论79阅读模式
英文:

Printing Issue with Concurrent Routines in Go

问题

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

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)
}

现在我面临的问题是,有时候由于三个并发例程的结果,有时候打印语句不会正确执行,意味着没有完整地打印出来,有些内容被另一个打印插入了。例如,例程1的 Print (value a, value b, value c) 输出的结果是 value a, value b, value g,其中 value g 是由例程2插入的。有人能给我建议,我该如何解决这个问题?我已经尝试了 sync-mutex 过程。然而,可能是因为我的代码太长,可能我无法正确地放置锁定和解锁,所以它会给出死锁错误。有人能给我建议,我该如何以简单的方式实现这些,或者以更少风险的 sync-mutex 过程。

关于我的这个问题的更多信息可以在这里找到。

英文:

I have three concurrent routines like this,

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)
}

Now what problem I am facing is, sometimes it will happen that, as the result of three concurrent routines, sometimes the print statement is not executing properly means not printing whole, there is some thing inserted by another print. For example, Print (value a, value b, value c) of routine 1 gives output like value a, value b, value g where value g is inserted by routine 2. Can anybody suggest me, how can I stop it ? I have tried sync-mutex procedure. However may be as my code is too long and may be I can not put lock-unlock in a right way, so it is giving a deadlock error. Can anybody suggest me how can I implement those in a simple way or in a less risky sync-mutex procedure.

More info about this problem of mine can be found here.

答案1

得分: 6

按照您描述的方式打印并不是一个原子操作。不要使用互斥锁,而是尝试使用Go的方式。将一个通道传递给每个goroutine,该通道接受一个字符串。每次您想要打印一些内容时,只需将字符串发送到该通道中。

一个单独的goroutine只需从该通道中读取并打印出任何输出。这样就不需要锁。

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    wg.Add(2) // 我们需要等待的2个例程。

    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 <- "来自1的第一次打印"
    // 做一些事情
    stdout <- "来自1的第二次打印"
}

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

    stdout <- "来自2的第一次打印"
    // 做一些事情
    stdout <- "来自2的第二次打印"
}

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

Printing as you describe it is not an atomic operation. Instead of using mutexes, try the Go way. Pass a channel into each goroutine which accepts a string. Every time you want to print something, just send the string into that channel.

A separate goroutine does nothing more than read from that channel and prints whatever comes out. This way there is no need for locks.

package main

import (
    &quot;fmt&quot;
    &quot;sync&quot;
)

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

    stdout := make(chan string)

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

    wg.Wait()
    
    close(stdout)
}

func routine1(wg *sync.WaitGroup, stdout chan&lt;- string) {
    defer wg.Done()
    
    stdout &lt;- &quot;first print from 1&quot;
    // do stuff
    stdout &lt;- &quot;second print from 1&quot;
}

func routine2(wg *sync.WaitGroup, stdout chan&lt;- string) {
    defer wg.Done()
    
    stdout &lt;- &quot;first print from 2&quot;
    // do stuff
    stdout &lt;- &quot;second print from 2&quot;
}

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

huangapple
  • 本文由 发表于 2011年12月2日 19:40:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/8355795.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定