Проблема с печатью параллельных процедур в 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)
}

Теперь, с какой проблемой я столкнулся, иногда случается, что в результате трех одновременных процедур иногда оператор печати не выполняется должным образом, что означает, что он не печатает целиком, есть что-то, вставленное другим отпечатком. Например, Print (значение a, значение b, значение c) подпрограммы 1 дает вывод, подобный значению a, значению b, значению g, где значение g вставляется подпрограммой 2. Может ли кто-нибудь предложить мне, как я могу это остановить? Я пробовал процедуру синхронизации-мьютекса. Однако, возможно, мой код слишком длинный, и, возможно, я не могу правильно поставить блокировку-разблокировку, поэтому он выдает ошибку взаимоблокировки. Может ли кто-нибудь предложить мне, как я могу реализовать их простым способом или менее рискованной процедурой синхронизации-мьютекса.

Дополнительную информацию об этой моей проблеме можно найти здесь.


person Arpssss    schedule 02.12.2011    source источник


Ответы (1)


Печать, как вы описываете, не является атомарной операцией. Вместо использования мьютексов попробуйте Go. Передайте канал в каждую горутину, которая принимает строку. Каждый раз, когда вы хотите что-то напечатать, просто отправьте строку в этот канал.

Отдельная горутина не делает ничего, кроме чтения из этого канала и печатает все, что выходит. Таким образом, нет необходимости в замках.

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)
        }
    }
}
person jimt    schedule 02.12.2011
comment
Спасибо. Это действительно приятная процедура. Дай мне попробовать. - person Arpssss; 02.12.2011