所有戈鲁丁都是睡眠僵局

模拟我真正的问题,我有这个代码。

基本上,数组“字母”的每个元素及其索引都被发送到goroutine以将其与“x”进行比较,然后通过通道发送响应。我的想法是它在“x”线程上运行,在实际情况下,我使用8个线程。


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()

}


四季花海
浏览 60回答 1
1回答

哈士奇WWW

声誉不足,无法发表评论。因此,为了代替注释,下面是代码的替代版本:package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "sync")var wg sync.WaitGroupconst sizeLetters = 12func detectX(ch2 chan int, j int, letters [sizeLetters]string) {&nbsp; &nbsp; if letters[j] == "x" {&nbsp; &nbsp; &nbsp; &nbsp; ch2 <- j&nbsp; &nbsp; }}func main() {&nbsp; &nbsp; ch1 := make(chan int)&nbsp; &nbsp; ch2 := make(chan int)&nbsp; &nbsp; letters := [sizeLetters]string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"}&nbsp; &nbsp; threads := 4&nbsp; &nbsp; wg.Add(threads)&nbsp; &nbsp; for i := 0; i < threads; i++ {&nbsp; &nbsp; &nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; j, ok := <-ch1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if !ok {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; detectX(ch2, j, letters)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }()&nbsp; &nbsp; }&nbsp; &nbsp; // Use a goroutine to close ch2. It is only safe to do this&nbsp; &nbsp; // after all the other goroutines have exited.&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; wg.Wait()&nbsp; &nbsp; &nbsp; &nbsp; close(ch2)&nbsp; &nbsp; }()&nbsp; &nbsp; for i := 0; i < sizeLetters; i++ {&nbsp; &nbsp; &nbsp; &nbsp; ch1 <- i // add i to the queue&nbsp; &nbsp; }&nbsp; &nbsp; close(ch1)&nbsp; &nbsp; if k, ok := <-ch2; ok && k != -1 { //when exist&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("X exist in position:", k)&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("X doesn´t exist")&nbsp; &nbsp; }}它仍然有一些与数据相关的问题(除非保证数组不包含重复项):letters也就是说,如果数组中有多个,则 goroutine 不会全部退出。也就是说,不会耗尽 。"x"main()ch2如果值的数量与值一样多,则代码将在顶层循环中死锁,因为写入将耗尽未阻塞的 goroutine 来使用它们。threads"x"formain()ch1如果您知道数组中可能有多少个值,则可以使通道深度为:。这将允许所有 goroutines 退出,但可能仍包含未拖累的数据。"x"lettersch2ch2 := make(chan int, depth)ch2
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go