20230122日志

20230122日志

2023年1月22日
2023
202301, condition

golang #

sync.cond #

type Donation struct {
  mu sync.RWMutex
  balance int
}
donation := &Donation{}
// Listener goroutines
f := func(goal int) {
  donation.mu.RLock()
  for donation.balance < goal {
    donation.mu.RUnlock()
    donation.mu.RLock()
  }
  fmt.Printf("$%d goal reached\n", donation.balance)
  donation.mu.RUnlock()
}
go f(10)
go f(15)
// Updater goroutine
go func() {
  for {
    time.Sleep(time.Second)
    donation.mu.Lock()
    donation.balance++
    donation.mu.Unlock()
  }
}()

cpu空转

type Donation struct {
  balance int
  ch chan int
}
donation := &Donation{ch: make(chan int)}
// Listener goroutines
f := func(goal int) {
  for balance := range donation.ch {
    if balance >= goal {
      fmt.Printf("$%d goal reached\n", balance)
      return
    }
  }
}
go f(10)
go f(15)
// Updater goroutine
for {
  time.Sleep(time.Second)
  donation.balance++
  donation.ch <- donation.balance
}

只能有一个goroutine能接收到10,print出来可能大于10

type Donation struct {
  cond *sync.Cond
  balance int
}
donation := &Donation{
  cond: sync.NewCond(&sync.Mutex{}),
}
// Listener goroutines
f := func(goal int) {
  donation.cond.L.Lock()
  for donation.balance < goal {
    donation.cond.Wait()
  }
  fmt.Printf("%d$ goal reached\n", donation.balance)
  donation.cond.L.Unlock()
}
go f(10)
go f(15)
// Updater goroutine
for {
  time.Sleep(time.Second)
  donation.cond.L.Lock()
  donation.balance++
  donation.cond.L.Unlock()
  donation.cond.Broadcast()
}

通过con让每个goroutine有机会接受检查

wait的机制

  1. unlock
  2. 暂停goroutine, wait notify
  3. notify arrive, lock

cond的缺点,向chan结构发送通知时,即使没有活动的接收方,消息也会被缓冲,保证了通知将在事件中被接收。 broadcast时,如果没有等待者,将会错过通知