Concurrency 使用并发技术的戈兰装配线

Concurrency 使用并发技术的戈兰装配线,concurrency,go,Concurrency,Go,新的开始。我试图编写一个“装配线”,其中多个函数像工人一样工作,并将一些数据结构传递给其他函数,每个函数都对数据结构做一些修改 type orderStruct struct { orderNum,capacity int orderCode uint64 box [9]int } func position0(in chan orderStruct){ order := <-in if((order.orderCode<<63)

新的开始。我试图编写一个“装配线”,其中多个函数像工人一样工作,并将一些数据结构传递给其他函数,每个函数都对数据结构做一些修改

type orderStruct struct {
    orderNum,capacity int
    orderCode uint64
    box [9]int
}


func position0(in chan orderStruct){

    order := <-in

    if((order.orderCode<<63)>>63 == 1){
        order.box[order.capacity] = 1
        order.capacity += 1
    }

    fmt.Println("  filling box {", order.orderNum, order.orderCode, order.box, order.capacity, "} at position 0")
}

func startOrder(in chan orderStruct){

    order := <-in

    fmt.Printf("\nStart an empty box for customer order number %d , request number %d\n", order.orderNum, order.orderCode)
    fmt.Println("  starting box {", order.orderNum, order.orderCode, order.box, order.capacity, "}")

    d := make(chan orderStruct,1)
    go position0(d)
    d <- order
}

func main() {

    var orders [10]orderStruct
    numOrders := len(os.Args)-1
    var x int

    for i := 0; i < numOrders; i++{
        x, _ = strconv.Atoi(os.Args[i+1])
        orders[i].orderCode = uint64(x)
        orders[i].orderNum = i+1
        orders[i].capacity = 0
        for j := 0; j < 9; j++{
            orders[i].box[j] = 0
        }
        c := make(chan orderStruct)
        go startOrder(c)
        c <- orders[i]
    }
}
类型orderStruct struct{
orderNum,容量int
订单代码uint64
方框[9]int
}
func位置0(在chan orderStruct中){

顺序:=我已尝试重新编写您编写的内容,以便正常工作。您可以

主要区别是

  • 只有两个go程序启动——它们充当生产线上的两个工人——一个接受订单,另一个填充箱
  • 使用来确定它们何时结束
  • 用于x:=范围通道的
  • 使用close(c)向通道末端发送信号
  • 您可以启动每个worker的多个副本,代码仍然可以正常工作(重复
    wg.Add(1);转到startOrders(c,wg)
    code)
这是密码

package main

import (
    "fmt"
    "sync"
)

type orderStruct struct {
    orderNum, capacity int
    orderCode          uint64
    box                [9]int
}

func position0s(in chan orderStruct, wg *sync.WaitGroup) {
    defer wg.Done()
    for order := range in {
        if (order.orderCode<<63)>>63 == 1 {
            order.box[order.capacity] = 1
            order.capacity += 1
        }
        fmt.Println("  filling box {", order.orderNum, order.orderCode, order.box, order.capacity, "} at position 0")
    }
}

func startOrders(in chan orderStruct, wg *sync.WaitGroup) {
    defer wg.Done()
    d := make(chan orderStruct)
    wg.Add(1)
    go position0s(d, wg)

    for order := range in {
        fmt.Printf("\nStart an empty box for customer order number %d , request number %d\n", order.orderNum, order.orderCode)
        fmt.Println("  starting box {", order.orderNum, order.orderCode, order.box, order.capacity, "}")
        d <- order
    }
    close(d)
}

func main() {
    var orders [10]orderStruct
    numOrders := 4
    var x int = 10
    wg := new(sync.WaitGroup)
    c := make(chan orderStruct)
    wg.Add(1)
    go startOrders(c, wg)
    for i := 0; i < numOrders; i++ {
        orders[i].orderCode = uint64(x)
        orders[i].orderNum = i + 1
        orders[i].capacity = 0
        for j := 0; j < 9; j++ {
            orders[i].box[j] = 0
        }
        c <- orders[i]
    }
    close(c)
    wg.Wait()
}
主程序包
进口(
“fmt”
“同步”
)
类型orderStruct struct{
orderNum,容量int
订单代码uint64
方框[9]int
}
func position0s(在chan orderStruct、wg*sync.WaitGroup中){
推迟工作组完成()
对于订单:=中的范围{
如果(order.orderCode63==1{
订单箱[订单容量]=1
订单容量+=1
}
fmt.Println(“填充框{”,order.orderNum,order.orderCode,order.box,order.capacity,}位于位置0”)
}
}
func startOrders(在chan orderStruct、wg*sync.WaitGroup中){
推迟工作组完成()
d:=make(chan orderStruct)
工作组.添加(1)
go位置0(d、wg)
对于订单:=中的范围{
fmt.Printf(“\n为客户订单号%d,请求号%d\n,order.orderNum,order.orderCode启动一个空框)
fmt.Println(“起始框{”,order.orderNum,order.orderCode,order.box,order.capacity,“}”)

当学习在围棋中同时编程时,管道是一个很好的起点。Nick Craig Wood的回答为这一特定挑战提供了一个有效的解决方案

在Go中使用并发还有一系列其他方法。大体上,根据被视为并发的内容分为三类:

  • 功能分解—创建多个功能的管道是一个很好的开始方式—这是您的问题所在。这很容易思考,也很有成效。但是,如果它发展到真正的并行硬件,很难很好地平衡负载。一切都以最慢的管道阶段的速度进行。

  • 几何分解-将数据划分为可独立处理(或无需太多通信)的单独区域。基于网格的系统广泛用于某些科学高性能计算领域,如天气预报

  • 农业-确定如何将要完成的工作分解为(大量)任务,并将这些任务逐个分配给“工人”,直到全部完成。通常,任务数量远远超过工人数量。这一类别包括所有所谓的“尴尬的平行”问题(令人尴尬的是,如果你无法让你的高性能系统提供线性加速,你看起来有点愚蠢)

我可以添加第四类的混合上述几种


关于这一点有很多文献,包括80年代和90年代Occam编程时代的许多文献。Go和Occam都使用CSP消息传递,因此问题类似。我会挑出这本有用的书(Chalmers和Tidmus 1996).

我建议阅读——在这个设计中有很多问题需要解决。(随机观察,在实际问题的一边:我曾经构建了一个并行处理大量事情的管道,其中唯一显式并发的部分是一些
go io.Copy(w,r)
s。并非所有内容都适合该模型,但当您可以对大部分代码隐藏并发性时,这会很有帮助。)为了便于阅读此代码,请记住一共有三个goroutine,包括显式启动的两个goroutine和主goroutine本身。因此,如果我想添加一个从positions0s传递结构的函数,我会添加wg.add(1)吗;将位置1s代码更改为位置0s?此外,当我将numOrders更改为5时,第5个框从未像前4个框那样填满?@Tarzan忘记了
wg.Wait()
!更新了答案。至于
位置1s
-是的,你可以这样做。在
startOrders
启动整个生产线可能会更有序-在那里创建所有渠道并将其传递给工人。