Проблема печати с параллельными процедурами в Go - PullRequest
2 голосов
/ 02 декабря 2011

У меня есть три параллельные подпрограммы, подобные этой,

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 не выполняется должным образомозначает не печатать целое, есть какая-то вещь, вставленная другим отпечатком.Например, Print (значение a, значение b, значение c) подпрограммы 1 дает выходные данные, такие как значение a, значение b, значение g, где значение g вставляется подпрограммой 2. Кто-нибудь может мне подсказать, как я могу это остановить?Я попробовал процедуру синхронизации-мьютекса.Однако, возможно, мой код слишком длинный, и, возможно, я не могу правильно поставить блокировку-разблокировку, поэтому он вызывает ошибку взаимоблокировки.Кто-нибудь может мне подсказать, как я могу реализовать их простым способом или менее рискованной процедурой sync-mutex.

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

1 Ответ

6 голосов
/ 02 декабря 2011

Печать, как вы описываете, не является атомарной операцией.Вместо использования мьютексов, попробуйте 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)
        }
    }
}
...