gpt4 book ai didi

arrays - Goroutines 共享 slice : : trying to understand a data race

转载 作者:IT王子 更新时间:2023-10-29 02:26:28 24 4
gpt4 key购买 nike

我尝试用 Go 编写一个程序,以在非常大的 DNA 序列文件中查找一些基因。我已经编写了一个 Perl 程序来执行此操作,但我想利用 goroutines 并行执行此搜索;)

因为文件很大,我的想法是一次读取 100 个序列,然后将分析发送到 goroutine,然后再次读取 100 个序列等。

我要感谢本网站的成员,感谢他们对 slice 和 goroutines 的真正有用的解释。

我已经进行了建议的更改,以使用由 goroutines 处理的 slice 的副本。但是 -race 执行仍然在 copy() 函数级别检测到一个数据竞争:

非常感谢您的意见!

    ==================
WARNING: DATA RACE
Read by goroutine 6:
runtime.slicecopy()
/usr/lib/go-1.6/src/runtime/slice.go:113 +0x0
main.main.func1()
test_chan006.go:71 +0xd8

Previous write by main goroutine:
main.main()
test_chan006.go:63 +0x3b7

Goroutine 6 (running) created at:
main.main()
test_chan006.go:73 +0x4c9
==================
[>5HSAA098909 BA098909 ...]
Found 1 data race(s)
exit status 66

line 71 is : copy(bufCopy, buf_Seq)
line 63 is : buf_Seq = append(buf_Seq, line)
line 73 is :}(genes, buf_Seq)




package main

import (
"bufio"
"fmt"
"os"
"github.com/mathpl/golang-pkg-pcre/src/pkg/pcre"
"sync"
)

// function read a list of genes and return a slice of gene names
func read_genes(filename string) []string {
var genes []string // slice of genes names
// Open the file.
f, _ := os.Open(filename)
// Create a new Scanner for the file.
scanner := bufio.NewScanner(f)
// Loop over all lines in the file and print them.
for scanner.Scan() {
line := scanner.Text()
genes = append(genes, line)
}
return genes
}

// function find the sequences with a gene matching gene[] slice
func search_gene2( genes []string, seqs []string) ([]string) {
var res []string

for r := 0 ; r <= len(seqs) - 1; r++ {
for i := 0 ; i <= len(genes) - 1; i++ {

match := pcre.MustCompile(genes[i], 0).MatcherString(seqs[r], 0)

if (match.Matches() == true) {
res = append( res, seqs[r]) // is the gene matches the gene name is append to res
break
}
}
}

return res
}
//###########################################

func main() {
var slice []string
var buf_Seq []string
read_buff := 100 // the number of sequences analysed by one goroutine

var wg sync.WaitGroup
queue := make(chan []string, 100)

filename := "fasta/sequences.tsv"
f, _ := os.Open(filename)
scanner := bufio.NewScanner(f)
n := 0
genes := read_genes("lists/genes.csv")

for scanner.Scan() {
line := scanner.Text()
n += 1
buf_Seq = append(buf_Seq, line) // store the sequences into buf_Seq
if n == read_buff { // when the read buffer contains 100 sequences one goroutine analyses them

wg.Add(1)

go func(genes, buf_Seq []string) {
defer wg.Done()
bufCopy := make([]string, len(buf_Seq))
copy(bufCopy, buf_Seq)
queue <- search_gene2( genes, bufCopy)
}(genes, buf_Seq)
buf_Seq = buf_Seq[:0] // reset buf_Seq
n = 0 // reset the sequences counter

}
}
go func() {
wg.Wait()
close(queue)
}()

for t := range queue {
slice = append(slice, t...)
}

fmt.Println(slice)
}

最佳答案

goroutines 只在 slice headers 的副本上工作,底层数组是相同的。要制作 slice 的副本,您需要使用 copy(或 append 到不同的 slice )。

buf_Seq = append(buf_Seq, line)
bufCopy := make([]string, len(buf_Seq))
copy(bufCopy, buf_Seq)

然后您可以安全地将 bufCopy 传递给 goroutine,或者直接在闭包中使用它。

关于arrays - Goroutines 共享 slice : : trying to understand a data race,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38923237/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com