猿问

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

这是一个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 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


拉风的咖菲猫
浏览 81回答 1
1回答

大话西游666

程序有几个问题:1- for 循环创建 goroutines而备用票证的数量非零。这将创建许多 goroutine,因为它们不会立即执行并减少票数2- 在 buyTicket 中,您检查,然后购买。在一个 goroutine 检查、决定继续并买票后,另一个 goroutine 可以进去做同样的事情。解决方案是修复buyTicket在退出时锁定进入解锁,并在不调用getSpareTicket的情况下检查票数,因为getSpareTicket也锁定了相同的互斥体,这将导致死锁。
随时随地看视频慕课网APP

相关分类

Go
我要回答