为了账号安全,请及时绑定邮箱和手机立即绑定

所有戈鲁丁都是睡眠僵局

所有戈鲁丁都是睡眠僵局

Go
四季花海 2022-08-24 11:19:05
模拟我真正的问题,我有这个代码。基本上,数组“字母”的每个元素及其索引都被发送到goroutine以将其与“x”进行比较,然后通过通道发送响应。我的想法是它在“x”线程上运行,在实际情况下,我使用8个线程。package mainimport (    "strconv"    "sync")var wg sync.WaitGroupconst sizeLetters = 12func 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()}
查看完整描述

1 回答

?
哈士奇WWW

TA贡献1799条经验 获得超6个赞

声誉不足,无法发表评论。因此,为了代替注释,下面是代码的替代版本:


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

    }

}

它仍然有一些与数据相关的问题(除非保证数组不包含重复项):letters

  • 也就是说,如果数组中有多个,则 goroutine 不会全部退出。也就是说,不会耗尽 。"x"main()ch2

  • 如果值的数量与值一样多,则代码将在顶层循环中死锁,因为写入将耗尽未阻塞的 goroutine 来使用它们。threads"x"formain()ch1

    • 如果您知道数组中可能有多少个值,则可以使通道深度为:。这将允许所有 goroutines 退出,但可能仍包含未拖累的数据。"x"lettersch2ch2 := make(chan int, depth)ch2


查看完整回答
反对 回复 2022-08-24
  • 1 回答
  • 0 关注
  • 59 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信