英文:
Go routine blocks another go routine
问题
我有两个goroutine,它们使用相同的函数但不同的参数进行工作。当我运行程序时,它可以正常运行,但只有一个goroutine在工作,另一个goroutine由于某种原因处于死亡/休眠状态。
我使用了互斥锁来阻塞读写操作。我使用了两个互斥锁:
- mutexSearch:在busquedaBid函数中使用
- mutexCompare:在checkEqualityValues函数中使用
当一个goroutine获取锁并达到解锁时,它永远不会释放代码块,导致另一个goroutine永远无法工作。
这是我尝试过的解决方法:
package main
import (
"fmt"
"math"
"math/rand"
"sort"
"sync"
"time"
)
var mutexCompare sync.Mutex
type Cola struct {
tomarLista int
contadorSoluciones int
cola [][]int
}
func main() {
in := time.Now()
puzzleInicial := []int{1,2,3,4,5,6,7,8,0}
grafo := make(map[int][]int)
grafo[0] = []int{1, 3}
grafo[1] = []int{0, 2, 4}
grafo[2] = []int{1, 5}
grafo[3] = []int{0, 4, 6}
grafo[4] = []int{1, 3, 5, 7}
grafo[5] = []int{2, 4, 8}
grafo[6] = []int{3, 7}
grafo[7] = []int{4, 6, 8}
grafo[8] = []int{5, 7}
puzzleFinal := []int{1, 3, 6, 5, 2, 0, 4, 7, 8}
colaInicial := [][]int{}
colaFinal := [][]int{}
colaInicial = append(colaInicial, puzzleInicial)
colaFinal = append(colaFinal, puzzleFinal)
tomarListaInicial := 0
contadorSolucionesInicial := 0
mutexSearch := &sync.Mutex{}
done := make(chan bool)
colaI := Cola{tomarListaInicial, contadorSolucionesInicial, colaInicial}
colaF := Cola{tomarListaInicial, contadorSolucionesInicial, colaFinal}
go busquedaBid(&colaI, &colaF, grafo, mutexSearch, done)
go busquedaBid(&colaF, &colaI, grafo, mutexSearch, done)
<-done
f := time.Since(in)
fmt.Println(f)
}
func busquedaBid(colaActual *Cola, colaCheck *Cola, grafo map[int][]int, mut *sync.Mutex,
done chan bool) {
for {
mut.Lock()
nodo := getIndex(colaActual.cola[colaActual.tomarLista])
for _, neighbour := range grafo[nodo] {
sliceAux := append([]int(nil), colaActual.cola[colaActual.tomarLista]...)
valorAux := sliceAux[neighbour]
indCero := getIndex(sliceAux)
sliceAux[neighbour] = 0
sliceAux[indCero] = valorAux
if !checkRepetitionsSlices(colaActual.cola, sliceAux) {
colaActual.cola = append(colaActual.cola, sliceAux)
}
}
colaActual.tomarLista += 1
mut.Unlock()
if checkEqualityValues(colaActual.cola, colaCheck.cola, done) {
break
}
}
}
func checkEqualityValues(cola_inicial [][]int, cola_final [][]int, done chan bool) bool {
mutexCompare.Lock()
for _, item1 := range cola_inicial {
for _, item2 := range cola_final {
if checkRepetitionsSliceSlice(item1, item2) {
fmt.Println(len(cola_inicial), len(cola_final))
close(done)
return true
}
}
}
mutexCompare.Unlock()
return false
}
例如,这是一个输出:
115 1
这个输出告诉我只有一个goroutine在工作,因为另一个goroutine没有将任何切片放入队列(队列是一个切片的切片)。
如果我犯了一个大错误,我很抱歉,我是新手,正在学习Go语言。
英文:
I have two go rutines that are working with the same function, but with different params. When I run the program it runs well, but only 1 rutine was working, and the other was dead/sleeping for some reason.
I used mutex for block the read/write. I used two mutex:
- mutexSearch: To use in busquedaBid function
- mutexCompare: To use in checkEqualityValues function
When one rutine take the lock and reach the unlock it never releases the code block causing the other routine to never work.
This is what I tried:
package main
import (
"fmt"
"math"
"math/rand"
"sort"
"sync"
"time"
)
var mutexCompare sync.Mutex
type Cola struct {
tomarLista int
contadorSoluciones int
cola [][]int
}
func main() {
in := time.Now()
puzzleInicial := []int{1,2,3,4,5,6,7,8,0}
grafo := make(map[int][]int)
grafo[0] = []int{1, 3}
grafo[1] = []int{0, 2, 4}
grafo[2] = []int{1, 5}
grafo[3] = []int{0, 4, 6}
grafo[4] = []int{1, 3, 5, 7}
grafo[5] = []int{2, 4, 8}
grafo[6] = []int{3, 7}
grafo[7] = []int{4, 6, 8}
grafo[8] = []int{5, 7}
puzzleFinal := []int{1, 3, 6, 5, 2, 0, 4, 7, 8}
colaInicial := [][]int{}
colaFinal := [][]int{}
colaInicial = append(colaInicial, puzzleInicial)
colaFinal = append(colaFinal, puzzleFinal)
tomarListaInicial := 0
contadorSolucionesInicial := 0
mutexSearch := &sync.Mutex{}
done := make(chan bool)
colaI := Cola{tomarListaInicial, contadorSolucionesInicial, colaInicial}
colaF := Cola{tomarListaInicial, contadorSolucionesInicial, colaFinal}
go busquedaBid(&colaI, &colaF, grafo, mutexSearch, done)
go busquedaBid(&colaF, &colaI, grafo, mutexSearch, done)
<-done
f := time.Since(in)
fmt.Println(f)
}
func busquedaBid(colaActual *Cola, colaCheck *Cola, grafo map[int][]int, mut *sync.Mutex,
done chan bool) {
for {
mut.Lock()
nodo := getIndex(colaActual.cola[colaActual.tomarLista])
for _, neighbour := range grafo[nodo] {
sliceAux := append([]int(nil), colaActual.cola[colaActual.tomarLista]...)
valorAux := sliceAux[neighbour]
indCero := getIndex(sliceAux)
sliceAux[neighbour] = 0
sliceAux[indCero] = valorAux
if !checkRepetitionsSlices(colaActual.cola, sliceAux) {
colaActual.cola = append(colaActual.cola, sliceAux)
}
}
colaActual.tomarLista += 1
mut.Unlock()
if checkEqualityValues(colaActual.cola, colaCheck.cola, done) {
break
}
}
}
func checkEqualityValues(cola_inicial [][]int, cola_final [][]int, done chan bool) bool {
mutexCompare.Lock()
for _, item1 := range cola_inicial {
for _, item2 := range cola_final {
if checkRepetitionsSliceSlice(item1, item2) {
fmt.Println(len(cola_inicial), len(cola_final))
close(done)
return true
}
}
}
mutexCompare.Unlock()
return false
}
For example this is an output:
115 1
That output says to me that only one rutine was worked, because the other one didn't put any slice in the queue (the queue it's a slice of slices)
Sorry if a maked a bigmistake, I'm new and I'm learning go
答案1
得分: 1
我认为我解决了这个问题。我创建了一个包含3个goroutine的for循环:
- 两个用于函数"busquedaBid"(这个函数执行一种双向搜索)
- 一个用于"checkEqualityValues"(这个函数确定两个切片是否相等)
此外,我使用了sync.WaitGroup
,并在函数中放置了wg.Done()
语句,解决了例程之间的阻塞问题。
(我不知道这个解决方案是否符合Go的方式)
package main
import (
"fmt"
"math"
"math/rand"
"sort"
"sync"
"time"
)
var mutexCompare sync.Mutex
var flag bool = false
type Cola struct {
tomarLista int
contadorSoluciones int
cola [][]int
}
func main() {
in := time.Now()
puzzleInicial := []int{1,2,3,4,5,6,7,8,0}
grafo := make(map[int][]int)
grafo[0] = []int{1, 3}
grafo[1] = []int{0, 2, 4}
grafo[2] = []int{1, 5}
grafo[3] = []int{0, 4, 6}
grafo[4] = []int{1, 3, 5, 7}
grafo[5] = []int{2, 4, 8}
grafo[6] = []int{3, 7}
grafo[7] = []int{4, 6, 8}
grafo[8] = []int{5, 7}
puzzleFinal := []int{1, 3, 6, 5, 2, 0, 4, 7, 8}
colaInicial := [][]int{}
colaFinal := [][]int{}
colaInicial = append(colaInicial, puzzleInicial)
colaFinal = append(colaFinal, puzzleFinal)
mutexSearch := &sync.Mutex{}
colaI := Cola{0, 0, colaInicial}
colaF := Cola{0, 0, colaFinal}
mutexSearch := &sync.Mutex{}
wg := &sync.WaitGroup{}
for {
if flag {
return
}
wg.Add(3)
go busquedaBid(&colaF, &colaI, grafo, mutexSearch, wg)
go busquedaBid(&colaI, &colaF, grafo, mutexSearch, wg)
go checkEqualityValues(colaI.cola, colaF.cola, wg)
wg.Wait()
}
}
func busquedaBid(colaActual *Cola, colaCheck *Cola, grafo map[int][]int, mut *sync.Mutex, wg *sync.WaitGroup) {
mut.Lock()
nodo := getIndex(colaActual.cola[colaActual.tomarLista])
for _, neighbour := range grafo[nodo] {
sliceAux := append([]int(nil), colaActual.cola[colaActual.tomarLista]...)
sliceAux[getIndex(sliceAux)] = sliceAux[neighbour]
sliceAux[neighbour] = 0
if checkRepetitionsMapSlice(colaActual.cola, sliceAux) == false {
colaActual.cola = append(colaActual.cola, sliceAux)
}
}
colaActual.tomarLista += 1
mut.Unlock()
wg.Done()
}
func checkEqualityValues(cola_inicial [][]int, cola_final [][]int, wg *sync.WaitGroup) {
mutexCompare.Lock()
for _, item1 := range cola_inicial {
for _, item2 := range cola_final {
if checkRepetitionsSliceSlice(item1, item2) {
flag = true
fmt.Println(runtime.NumGoroutine())
mutexCompare.Unlock()
wg.Done()
}
}
}
mutexCompare.Unlock()
wg.Done()
}
英文:
I think I solve the problem. I made a for loop that contains 3 goroutines:
- Two for the function "busquedaBid" (this function make a type of bidirectional search)
- One for "checkEqualityValues" (this function determines if two slices are equals)
Adittionally I used sync.WaitGroup
and I puted the wg.Done()
sentence in functions, that solve the block problem between routines.
(I don't know if this solution is in a go way)
package main
import (
"fmt"
"math"
"math/rand"
"sort"
"sync"
"time"
)
var mutexCompare sync.Mutex
var flag bool = false
type Cola struct {
tomarLista int
contadorSoluciones int
cola [][]int
}
func main() {
in := time.Now()
puzzleInicial := []int{1,2,3,4,5,6,7,8,0}
grafo := make(map[int][]int)
grafo[0] = []int{1, 3}
grafo[1] = []int{0, 2, 4}
grafo[2] = []int{1, 5}
grafo[3] = []int{0, 4, 6}
grafo[4] = []int{1, 3, 5, 7}
grafo[5] = []int{2, 4, 8}
grafo[6] = []int{3, 7}
grafo[7] = []int{4, 6, 8}
grafo[8] = []int{5, 7}
puzzleFinal := []int{1, 3, 6, 5, 2, 0, 4, 7, 8}
colaInicial := [][]int{}
colaFinal := [][]int{}
colaInicial = append(colaInicial, puzzleInicial)
colaFinal = append(colaFinal, puzzleFinal)
mutexSearch := &sync.Mutex{}
colaI := Cola{0, 0, colaInicial}
colaF := Cola{0, 0, colaFinal}
mutexSearch := &sync.Mutex{}
wg := &sync.WaitGroup{}
for {
if flag {
return
}
wg.Add(3)
go busquedaBid(&colaF, &colaI, grafo, mutexSearch, wg)
go busquedaBid(&colaI, &colaF, grafo, mutexSearch, wg)
go checkEqualityValues(colaI.cola, colaF.cola, wg)
wg.Wait()
}
}
func busquedaBid(colaActual *Cola, colaCheck *Cola, grafo map[int][]int, mut *sync.Mutex, wg *sync.WaitGroup) {
mut.Lock()
nodo := getIndex(colaActual.cola[colaActual.tomarLista])
for _, neighbour := range grafo[nodo] {
sliceAux := append([]int(nil), colaActual.cola[colaActual.tomarLista]...)
sliceAux[getIndex(sliceAux)] = sliceAux[neighbour]
sliceAux[neighbour] = 0
if checkRepetitionsMapSlice(colaActual.cola, sliceAux) == false {
colaActual.cola = append(colaActual.cola, sliceAux)
}
}
colaActual.tomarLista += 1
mut.Unlock()
wg.Done()
}
func checkEqualityValues(cola_inicial [][]int, cola_final [][]int, wg *sync.WaitGroup) {
mutexCompare.Lock()
for _, item1 := range cola_inicial {
for _, item2 := range cola_final {
if checkRepetitionsSliceSlice(item1, item2) {
flag = true
fmt.Println(runtime.NumGoroutine())
mutexCompare.Unlock()
wg.Done()
}
}
}
mutexCompare.Unlock()
wg.Done()
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论