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

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

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

Go
芜湖不芜 2022-09-19 20:51:23
为什么此代码仅在<时有效;在结果之前<-味精;?我认为<-sem为新的子例程释放了缓冲区。除此之外,有没有更好的方法从go例程中的函数返回结果?从逻辑上讲,我想这样做,但它不起作用,除非<-sem高于结果<-msg。var msg = printer(account)results<-msg;<-sem;这是我的代码:package mainimport (    "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)        }    }}
查看完整描述

1 回答

?
慕慕森

TA贡献1856条经验 获得超17个赞

因此,通道使用 len= 的缓冲区进行初始化sem2

这允许程序在此通道中推送两次,然后再阻止 。sem <- true //block

要从频道中释放房间,您可以在完成工作后读取一个值,这意味着到现在为止,其他人可以再次推送到频道并继续。<-semsem <- true //block

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

var msg = 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


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

添加回答

举报

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