如何对多个 goroutine 共享的数据结构执行并发操作

我在 Go 中解决了一个难题,它通过旋转 ASCII 字节值以匹配行方式(左->右)或列方式(顶部->底部)的字符串,在 2D 字节数组中找到一个字符串。我能够按顺序解决它,当它同时解决它时,我尝试启动一个 go-routine 来处理特定的输入组合,看看是否有任何可能的 25 个旋转可以找到匹配项。代码摘要如下


该FindByConcurrentRot方法采用 2D 字符数组输入并尝试在各种可能的输入组合中找到字符串的匹配项。


问题是 - 下面使用的并发方法是否有效?如何改进?将顺序例程“按原样”转换为并发程序的方法是否错误?即是否应该重写整个程序以充分利用并发特性?


// searchResult defines the information needed to pass to identify if a match has been identified during concurrent search

type searchResult struct {

    row   int

    col   int

    rot   int

    found bool

}


// processSearchResults runs the gorotuine to perform the search for a particular rotation of input

func processSearchResults(wg *sync.WaitGroup, iter int, resultChan chan searchResult, table [][]byte, word string) {

    // call goroutine end when the function returns

    defer wg.Done()

    if iter >= 1 {

        rotate(table, iter)

    }

    x, y, match := present(table, word)

    if match {

        resultChan <- searchResult{row: x, col: y, rot: iter, found: true}

        return

    }

    resultChan <- searchResult{found: false}

}


// doCopy creates a copy of the original table to passed for each iteration of the concurrent search

// This is an EXPENSIVE operation on a goroutine, because of memory copy operations

// The copy is needed for the goroutines to have their own control of data and not run into data

// races by passing the original data to each of them

func doCopy(table [][]byte) [][]byte {

    copyTable := make([][]byte, len(table))

    for i := range table {

        copyTable[i] = make([]byte, len(table[i]))

        copy(copyTable[i], table[i])

    }

    return copyTable

}

此 Go 操场链接上的完整 MVCE - https://go.dev/play/p/7YFAsAlFRUw

慕田峪7331174
浏览 112回答 1
1回答

慕码人2483693

这种方法很可能会因复制表所花费的周期过多而受到影响。由于每个 goroutine 都在修改表,因此每个 goroutine 都必须获得一个单独的副本。另一种方法是在只读表的顶部添加一个层,为每个 goroutine 提供修改后的视图。这并不能保证更好的性能,但它可能比使用多个 goroutine 复制的性能更好。方法是有一个表格视图:type tableView struct {&nbsp; &nbsp;inc int&nbsp; &nbsp;table [][]byte}func (t tableView) get(row,col int) byte {&nbsp; &nbsp;v:=t.table[row][col]&nbsp; &nbsp;v+=t.inc&nbsp; &nbsp;if v>'z' {...}&nbsp; &nbsp;return v}然后,您初始化并传递一个 tableView 实例。再说一遍:这可能不会像您期望的那样快,但它可能比表的多个副本执行得更好。您必须测试并查看。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go