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
启动整个生产线可能会更有序-在那里创建所有渠道并将其传递给工人。