Mensimulasikan masalah saya yang sebenarnya, saya memiliki kode ini.
Pada dasarnya, setiap elemen larik "huruf" beserta indeksnya dikirim ke goroutine untuk membandingkannya dengan "x", lalu mengirimkan respons melalui saluran. Ide saya adalah ini berjalan pada utas "x", dalam kasus nyata saya menggunakan 8 utas.

package main

import (
    "strconv"
    "sync"
)

var wg sync.WaitGroup
const sizeLetters = 12

func detectX(ch2 chan int, j int, letters [sizeLetters]string) {
    if letters[j] == "x" {
        ch2 <- j
    }else{
        ch2 <- -1
    }
}


func main() {
    ch1 := make(chan int)
    ch2 := make(chan int)
    letters := [sizeLetters]string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"}
    threads:= 4
    wg.Add(threads)
    for i := 0; i < threads; i++ {
        go func() {
            for {
                j, ok := <-ch1
                if !ok {
                    wg.Done()
                }
                detectX(ch2, j, letters)
            }
        }()
    }
    for i := 0; i < sizeLetters; i++ {
        ch1<-i // add i to the queue
    }
    k, ok := <-ch2 //k contains the position of X, if exist
    if !ok {
        wg.Done()
    }
    if k != -1 { //when exist
        println("X exist in position: " + strconv.Itoa(k))
    }
    println("X doesn´t exist")
    close(ch2)
    close(ch1)
    wg.Wait()
}

0
José Guzmán 4 April 2021, 12:18

1 menjawab

Jawaban Terbaik

Reputasi tidak cukup untuk berkomentar. Jadi, sebagai pengganti komentar, berikut adalah versi alternatif dari kode:

package main

import (
    "fmt"
    "sync"
)

var wg sync.WaitGroup

const sizeLetters = 12

func detectX(ch2 chan int, j int, letters [sizeLetters]string) {
    if letters[j] == "x" {
        ch2 <- j
    }
}

func main() {
    ch1 := make(chan int)
    ch2 := make(chan int)
    letters := [sizeLetters]string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"}
    threads := 4
    wg.Add(threads)
    for i := 0; i < threads; i++ {
        go func() {
            for {
                j, ok := <-ch1
                if !ok {
                    wg.Done()
                    return
                }
                detectX(ch2, j, letters)
            }
        }()
    }
    // Use a goroutine to close ch2. It is only safe to do this
    // after all the other goroutines have exited.
    go func() {
        wg.Wait()
        close(ch2)
    }()
    for i := 0; i < sizeLetters; i++ {
        ch1 <- i // add i to the queue
    }
    close(ch1)
    if k, ok := <-ch2; ok && k != -1 { //when exist
        fmt.Println("X exist in position:", k)
    } else {
        fmt.Println("X doesn´t exist")
    }
}

Masih memiliki beberapa masalah yang bergantung pada data (kecuali array letters dijamin tidak mengandung duplikat):

  • Yaitu, jika ada lebih dari satu "x" dalam larik, goroutine tidak akan keluar semuanya. Artinya, main() tidak menguras ch2.
  • Jika ada sebanyak threads "x" nilai, maka kode akan menemui jalan buntu di loop for tingkat atas di main() karena penulisan ke ch1 akan berjalan keluar dari goroutine yang tidak diblokir untuk mengkonsumsinya.
    • Jika Anda mengetahui berapa banyak nilai "x" yang mungkin dalam larik letters, Anda dapat membuat saluran ch2 sedalam itu: ch2 := make(chan int, depth). Ini akan memungkinkan semua goroutine keluar, tetapi ch2 berpotensi masih berisi data yang tidak terdrainase.
0
Tinkerer 5 April 2021, 18:58