登录
首页 >  Golang >  Go问答

为什么 sleep 会禁用 go 中的互斥体?

来源:stackoverflow

时间:2024-03-30 16:36:33 498浏览 收藏

一分耕耘,一分收获!既然打开了这篇文章《为什么 sleep 会禁用 go 中的互斥体?》,就坚持看下去吧!文中内容包含等等知识点...希望你能在阅读本文后,能真真实实学到知识或者帮你解决心中的疑惑,也欢迎大佬或者新人朋友们多留言评论,多给建议!谢谢!

问题内容

这是一个buyticket程序,当ticket为0时,会显示“sell out”。我想知道为什么我不能在 buyticket 函数中添加 sleep 以及为什么 ticket 会是负数?

func(t *ticket) buyticket() {
        if t.getspareticket() <= 0 {
            log.print("sell out")
            return
        }
        t.mu.lock()
        t.numticket--
        time.sleep(time.microsecond)
        log.printf("there are %d", t.numticket)
        t.mu.unlock()
    }
    
    func (t *ticket) getspareticket() int{
        t.mu.lock()
        defer t.mu.unlock()
        return t.numticket
    }
    
    
    func main() {
        buyer := &ticket{}
        buyer.mu = sync.mutex{}
        buyer.numticket = 100
        for buyer.getspareticket() > 0 {
            //time.sleep(time.microsecond)
            go func() {
                log.printf("number buy a ticket")
                buyer.buyticket()
            }()
        }
    
        time.sleep(time.second * 2)
        //l := buyer.getspareticket()
        //fmt.println(l)
    }

当我在 buyticket 函数中添加 time.sleep(time.microsecond) 时,票证将为负数,我想知道为什么会发生这种情况?

这是结果:

2020/11/15 15:36:00 there are 2
2020/11/15 15:36:00 there are 1
2020/11/15 15:36:00 there are 0
2020/11/15 15:36:00 there are -1
2020/11/15 15:36:00 there are -2
2020/11/15 15:36:00 there are -3
2020/11/15 15:36:00 there are -4
2020/11/15 15:36:00 there are -5

解决方案


该程序存在几个问题:

1- for 循环创建 goroutine,而备用票数不为零。这将创建许多 goroutine,因为它们不会立即执行并减少票数

2- 在 buyTicket 中,您检查,然后购买。在一个 Goroutine 检查后,另一个 Goroutine 可以进去做同样的事情,决定继续并买一张票。

解决方案是修复 buyTicket 以在退出时锁定入口解锁,并在不调用 getSpareTicket 的情况下检查票证计数,因为 getSpareTicket 也会锁定相同的互斥锁,这将导致死锁。

本篇关于《为什么 sleep 会禁用 go 中的互斥体?》的介绍就到此结束啦,但是学无止境,想要了解学习更多关于Golang的相关知识,请关注golang学习网公众号!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>