这是一个buyTicket程序,当ticket为0时,会显示“sell out”。我想知道为什么我不能在 buyTicket 函数中添加睡眠以及为什么票会是负数?
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)
}
Run Code Online (Sandbox Code Playgroud)
当我在函数 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
Run Code Online (Sandbox Code Playgroud)
程序有几个问题:
1- for 循环创建 goroutine,而备用票的数量不为零。这将创建许多 goroutine,因为它们不会立即执行并减少工单数量
2- 在buyTicket 中,您检查,然后购买。另一个goroutine可以在一个goroutine检查后做同样的事情,决定继续并买票。
解决方法是修复buyTicket在退出时锁定进入解锁,并且不调用getSpareTicket检查票数,因为getSpareTicket也锁定了同一个互斥锁,这会导致死锁。
| 归档时间: |
|
| 查看次数: |
95 次 |
| 最近记录: |