Go协程阻塞了另一个Go协程。

huangapple go评论82阅读模式
英文:

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 (
&quot;fmt&quot;
&quot;math&quot;
&quot;math/rand&quot;
&quot;sort&quot;
&quot;sync&quot;
&quot;time&quot;
)
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 := &amp;sync.Mutex{}
done := make(chan bool)
colaI := Cola{tomarListaInicial, contadorSolucionesInicial, colaInicial}
colaF := Cola{tomarListaInicial, contadorSolucionesInicial, colaFinal}
go busquedaBid(&amp;colaI, &amp;colaF, grafo, mutexSearch, done)
go busquedaBid(&amp;colaF, &amp;colaI, grafo, mutexSearch, done)
&lt;-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 (
&quot;fmt&quot;
&quot;math&quot;
&quot;math/rand&quot;
&quot;sort&quot;
&quot;sync&quot;
&quot;time&quot;
)
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 := &amp;sync.Mutex{}
colaI := Cola{0, 0, colaInicial}
colaF := Cola{0, 0, colaFinal}
mutexSearch := &amp;sync.Mutex{}
wg := &amp;sync.WaitGroup{}
for {
if flag {
return
}
wg.Add(3)
go busquedaBid(&amp;colaF, &amp;colaI, grafo, mutexSearch, wg)
go busquedaBid(&amp;colaI, &amp;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()
}

huangapple
  • 本文由 发表于 2023年6月22日 13:45:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76528885.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定