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

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

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

Go
拉风的咖菲猫 2022-07-11 17:14:52
这是一个buyTicket程序,当ticket为0时,会显示“sell out”。我想知道为什么我不能在 buyTicket 函数中添加 sleep 以及为什么票会是负数? 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) 时,ticket 将为负数,我想知道为什么会这样?这是结果:2020/11/15 15:36:00 there are 22020/11/15 15:36:00 there are 12020/11/15 15:36:00 there are 02020/11/15 15:36:00 there are -12020/11/15 15:36:00 there are -22020/11/15 15:36:00 there are -32020/11/15 15:36:00 there are -42020/11/15 15:36:00 there are -5
查看完整描述

1 回答

?
大话西游666

TA贡献1817条经验 获得超14个赞

程序有几个问题:

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

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

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


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

添加回答

举报

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