首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >片的并发处理

片的并发处理
EN

Code Review用户
提问于 2021-08-06 10:46:35
回答 1查看 1.3K关注 0票数 1

我正在努力学习Go并发模式和我自己的最佳实践。

我为自己发明了一个简单的任务。

我想以一种并行的方式处理一个整数片,把它分成几个子切片,然后用一个goroutine处理每一个。

下面是我目前的解决方案,我寻求建设性的代码审查。

如果您有任何问题或需要澄清/更新,请留下评论。

代码语言:javascript
复制
//  TASK:
//      given the slice of integers, multiply each element by 10
//      apply concurrency to solve this task by splitting slice into subslices and feeding them to goroutines
//  EXAMPLE:
//      input  -> slice := []int{  1,  2,  3,  4,  5,  6,  7,  8 }
//      output -> slice := []int{ 10, 20, 30, 40, 50, 60, 70, 80 }

package main

import (
    "fmt"
    "sync"
    "time"
)

func simulate_close_signal(quit chan bool, wg *sync.WaitGroup) {
    defer close(quit)
    defer wg.Done() // maybe I can remove this?

    for {
        select {
        case <-time.After(1 * time.Second):
            fmt.Println("Close signal sent")
            return
        }
    }
}

func process_subslice(quit chan bool,
    wg *sync.WaitGroup,
    original_slice []int,
    subslice_starting_index int,
    subslice_ending_index int,
    timeout func()) {

    defer wg.Done()
    for {
        select {
        case <-quit:
            fmt.Println("Goroutine: received request to close, quiting...")
            return
        default:
            // do I need mutex here? I think I don't since each goroutine processes independent subslice...
            original_slice[subslice_starting_index] = original_slice[subslice_starting_index] * 10
            subslice_starting_index++
            if subslice_starting_index >= subslice_ending_index {
                return
            }
            timeout() // added so I can test close signal
        }
    }
}

func main() {

    slice := []int{1, 2, 3, 4, 5, 6, 7, 8}
    fmt.Println("Starting slice: ", slice)

    quit := make(chan bool)

    wg := sync.WaitGroup{}

    for i := 0; i < 2; i++ {
        wg.Add(1)
        go process_subslice(quit,
            &wg,
            slice,
            i*4,     // this way slice is divided
            (1+i)*4, // in two subslices with indexes [0, 3] and [4,7]
            func() { time.Sleep(1 * time.Second) }) // pass empty func to test normal execution
    }

    wg.Add(1)
    go simulate_close_signal(quit, &wg)

    wg.Wait()

    fmt.Println("Processed slice: ", slice)

}

围棋游乐场

EN

回答 1

Code Review用户

回答已采纳

发布于 2021-08-09 04:36:49

看起来不错,正如您所写的,您不需要simulate_close_signal在等待组中,因为wg.Wait调用将在稍后同步其他两个写入slice的访问。

除此之外,您还可以将quit通道设置为chan struct{},因为没有任何东西正在编写或读取,因此唯一的目的是能够将其转化为close,因此您可以将其显式化。

像这样划分切片当然是可行的,尽管我确实建议您只创建一个实际的子切片,而不是传递索引,这就是它们的目的(它们都将共享基础数组,只需指向它的不同部分)。或者,如果不需要切片功能(例如,[8]int{1, 2, 3, 4, 5, 6, 7, 8}),则可以创建一个具有固定维度的实际数组。

编辑:请注意,现在我实际上是在操场上跑的。您发布的版本一致地给出了[10 20 3 4 50 60 7 8]的结果?你在发帖前试过吗?

来自quit的非阻塞读取并不像您所希望的那样工作。如果简单地打印乘法部分中的某个内容,您会注意到它两次进入这个块--这是可能发生的,因为还没有从quit通道读取任何内容。通常我会说你可以简单地放弃select,它在这里没有用。或者,您必须处理被执行一次、两次、更多甚至永远不执行的default案例!

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/265766

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档