使用信号量并发限制,为什么我必须先释放缓冲区?

为什么此代码仅在<时有效;在结果之前<-味精;?我认为<-sem为新的子例程释放了缓冲区。除此之外,有没有更好的方法从go例程中的函数返回结果?


从逻辑上讲,我想这样做,但它不起作用,除非<-sem高于结果<-msg。


var msg = printer(account)

results<-msg;

<-sem;

这是我的代码:


package main


import (

    "fmt"

    "strconv"

    "time"

    //"runtime"

    "math/rand"

)


var intSlice = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}


func printer(account int) string {

     n := rand.Intn(1) 

    fmt.Printf("Sleeping %d seconds...\n", n)

    time.Sleep(time.Duration(n)*time.Second)

    return "Account Done " + strconv.Itoa(account) 

}


func main() {

    threads := 2

    

    results := make(chan string, threads)

   

    sem := make(chan bool, threads)


    for _, account := range intSlice {

        sem <- true //block

        

        go func(account int) {

            var msg = printer(account)

            defer func() { <-sem; results<-msg; }()

        }(account)

    }

    

    for i := 0; i < cap(sem); i++ {

        sem <- true

    }

    

    for i := 0; i < len(intSlice); i++ {

        select {

        case msg1 := <-results:

            fmt.Println("received", msg1)

        }

    }


}


芜湖不芜
浏览 85回答 1
1回答

慕慕森

因此,通道使用 len= 的缓冲区进行初始化sem2这允许程序在此通道中推送两次,然后再阻止 。sem <- true //block要从频道中释放房间,您可以在完成工作后读取一个值,这意味着到现在为止,其他人可以再次推送到频道并继续。<-semsem <- true //block从逻辑上讲,我想这样做,但它不起作用,除非<-sem高于结果<-msg。var&nbsp;msg&nbsp;=&nbsp;printer(account) results<-msg; <-sem;你不能写这个,因为你在 阻止.由于读者尚未消费,因此没有任何内容允许这些指令向前推进。results<-msgresults真正发生的事情是,您正在堆栈上累积到一个单独的例程中阻塞到 at 上的例程。len(sem)len(results)results <- msg当您到达该循环时,它们会松开,但它们不会,因为阻止等待那些堆栈上的例程以使用释放空间。for i := 0; i < len(intSlice); i++ {mainsem <- true //block<-sem
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go