加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

并发 – 打印到stdout导致阻止的goroutine运行?

发布时间:2020-12-15 03:06:04 所属栏目:Java 来源:网络整理
导读:作为一个愚蠢的基本线程练习,我一直在尝试在golang中实现 sleeping barber problem.有渠道这应该很容易,但我遇到了heisenbug.也就是说,当我尝试诊断它时,问题就消失了! 考虑以下. main()函数将整数(或“客户”)推送到商店渠道. barber()阅读商店频道以剪掉
作为一个愚蠢的基本线程练习,我一直在尝试在golang中实现 sleeping barber problem.有渠道这应该很容易,但我遇到了heisenbug.也就是说,当我尝试诊断它时,问题就消失了!

考虑以下. main()函数将整数(或“客户”)推送到商店渠道. barber()阅读商店频道以剪掉“顾客”的头发.如果我将fmt.Print语句插入customer()函数,程序将按预期运行.否则,理发师()永远不会削减任何人的头发.

package main

import "fmt"

func customer(id int,shop chan<- int) {
    // Enter shop if seats available,otherwise leave
    // fmt.Println("Uncomment this line and the program works")
    if len(shop) < cap(shop) {
        shop <- id
    }
}

func barber(shop <-chan int) {
    // Cut hair of anyone who enters the shop
    for {
        fmt.Println("Barber cuts hair of customer",<-shop)
    }
}

func main() {
    shop := make(chan int,5) // five seats available
    go barber(shop)
    for i := 0; ; i++ {
        customer(i,shop)
    }
}

知道正在发生什么吗?

解决方法

问题是Go的调度程序的实现方式.只有在进行系统调用或阻塞通道操作时,当前goroutine才能产生其他goroutine. fmt.Println进行系统调用,为goroutine提供了屈服的机会.否则就没有.

在实践中,这通常并不重要,但对于像这样的小问题,它有时会突然出现.

此外,在频道上进行非阻塞发送的更惯用,更少生动的方式是:

func customer(id int,otherwise leave
    select {
    case shop <- id:
    default:
    }
}

你这样做的方式,客户可能最终会在理发店外等待,因为当你实际发送邮件时,len(商店)可能已经改变了.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读