Go中的并发制作人和消费者

时间:2013-12-23 13:31:15

标签: concurrency go producer

我想在Go中使用manager程序创建一个生产者/消费者。例如:我有5 producers, 5 consumers and manager。生产者有their own local arrays,他们迭代它们并将元素发送给经理。消费者their own local arrays有关于元素消耗的信息;他们也把它们发给了经理。管理器有own array,它存储有哪些元素和多少元素(例如 - 如果生成器发送1 1 2 3 1 2 0个元素,则管理器数组看起来像1 3 2 1(一个0,三个) 1,两个2和一个3)它处理生产者和消费者的请求 - 将一个元素放入数组(生成)或删除它(消费)。

是否可以在Go中制作这样的程序?我已经在JAVA + CSP中使用通道在管理器中发送信息和警卫,以确定当生产者和消费者尝试处理相同的元素时应该首先执行哪个过程(例如,生产者想要向管理器数组添加1)同时消费者想要消费1)。

欢迎提供任何示例或建议,因为我找不到任何关于我想做什么的信息。如果需要,我可以提供我的JAVA + CSP代码。

UPDATE。同步怎么样(不从空数组中获取)?例如 - 如果消费者想要从尚不存在的经理数组中消耗元素(例如,消费者想要消费'3',但经理没有任何这些),但生产者有这个元素,并且它将在几个之后生成迭代 - 如何让消费者一次又一次地检查管理器数组,直到生产者工作完成?我是否需要为使用者元素创建结构(或类)并标记它们是否被使用,或者Go是否有特定的方法来执行此操作?

2 个答案:

答案 0 :(得分:2)

我做了一个与你要做的事情非常相似的例子,请查看这个要点github gist

我实现的方式是为我的流程使用者使用单个通道,为生产项目的2x流程使用另一个通道,for块控制从生产者到消费者的推送以及生产者不推送任何东西时循环将default。通过通道移动的对象是切片,进程将生成并消耗通过通道发送的每个切片中的标题。我相信您可以调整此代码以适合您的示例。

答案 1 :(得分:2)

这是一个完整的例子,包括频道清理。在完成所有消费者和生产者之后,管理器打印出结果(我已经使用了地图而不是切片,因为我认为它使代码更容易)。

package main

import "fmt"

// Consume processes the numbers in ns, sending them on ch after they're
// processed. When the routine is finished, it signals that on done.
func Consume(done chan bool, ch chan int, ns []int) {
    for i := range ns {
        ch <- i
    }
    done <- true
}

// Produce "creates" the numbers in ns, sending them on ch after they're
// produced. When the routine is finished, it signals that on done.
func Produce(done chan bool, ch chan int, ns []int) {
    for i := range ns {
        ch <- i
    }
    done <- true
}

// Manage creates consumers and producers for the given int slices.
// It returns once all consumers and producers are finished.
func Manage(cons, pros [][]int) {
    cch := make(chan int)
    pch := make(chan int)
    dch := make(chan bool)
    n := len(cons) + len(pros)
    data := make(map[int]int)
    for _, c := range cons {
        go Consume(dch, cch, c)
    }
    for _, p := range pros {
        go Produce(dch, pch, p)
    }
    for n > 0 {
        select {
        case c := <-cch:
            data[c] -= 1
        case c := <-pch:
            data[c] += 1
        case <-dch:
            n -= 1
        }
    }
    close(cch)
    close(pch)
    close(dch)
    fmt.Println(data)
}
func main() {
    cons := [][]int{{1, 3, 5}, {0, 1, 5}}
    pros := [][]int{{0, 1, 1}, {3, 5, 5, 7}}
    Manage(cons, pros)
}