Wait(): 把当前的 goroutine 加入当前条件变量的通知队列.解锁当前条件变量基于的互斥锁、所以 wait 前必须加锁.当前 goroutine 阻塞在 wait()通知到来并唤醒了当前 goroutine 后 解锁当前条件变量基于的互斥锁执行后面的代码
Signal()Broadcast
上代码, 自己品:
package mainimport ("fmt""sync""time")type MailBox struct {count uint8locker sync.RWMutexsendCond *sync.CondrecvCond *sync.Cond}func (self *MailBox) Init() {self.sendCond = sync.NewCond(&self.locker)self.recvCond = sync.NewCond(self.locker.RLocker())}func (self *MailBox) Send() {self.locker.Lock()defer self.locker.Unlock()for self.count == 1 {fmt.Println("Send wait...")self.sendCond.Wait()}fmt.Println("Send")self.count = 1self.recvCond.Signal()}func (self *MailBox) Recv() {self.locker.RLock()defer self.locker.RUnlock()for self.count == 0 {fmt.Println("Recv wait...")self.recvCond.Wait()}fmt.Println("Recv")self.count = 0self.sendCond.Signal()}func main() {var mailBox MailBoxmailBox.Init()go func() {for i := 0; i < 5; i++ {mailBox.Send()}}()go func() {for i := 0; i < 5; i++ {mailBox.Recv()}}()time.Sleep(time.Second * 2)}
package mainimport ("fmt""sync""time")type MailBox struct {count uint8locker sync.RWMutexsendCond *sync.CondrecvCond *sync.Cond}func (self *MailBox) Init() {self.sendCond = sync.NewCond(&self.locker)self.recvCond = sync.NewCond(self.locker.RLocker())}func (self *MailBox) Send(i int) {fmt.Println(i)self.locker.Lock()fmt.Println(i, "lock")defer self.locker.Unlock()for self.count == 1 {fmt.Println(i, " Send wait...")self.sendCond.Wait()}fmt.Println(i, " Send")self.count = 1self.recvCond.Signal()}func (self *MailBox) Recv() {self.locker.RLock()defer self.locker.RUnlock()for self.count == 0 {fmt.Println("Recv wait...")self.recvCond.Wait()}fmt.Println("Recv")self.count = 0self.sendCond.Signal()}func main() {var mailBox MailBoxmailBox.Init()go func() {for i := 0; i < 5; i++ {mailBox.Send(i) // Send 里面的 for 循环会阻塞}}()time.Sleep(time.Second * 2)}
package mainimport ("fmt""sync""time")type MailBox struct {count uint8locker sync.RWMutexsendCond *sync.CondrecvCond *sync.Cond}func (self *MailBox) Init() {self.sendCond = sync.NewCond(&self.locker)self.recvCond = sync.NewCond(self.locker.RLocker())}func (self *MailBox) Send(i int) {fmt.Println(i)self.locker.Lock()fmt.Println(i, "lock")defer self.locker.Unlock()for self.count == 1 {fmt.Println(i, " Send wait...")self.sendCond.Wait()}fmt.Println(i, " Send")self.count = 1self.recvCond.Signal()}func (self *MailBox) Recv() {self.locker.RLock()defer self.locker.RUnlock()for self.count == 0 {fmt.Println("Recv wait...")self.recvCond.Wait()}fmt.Println("Recv")self.count = 0self.sendCond.Signal()}func main() {var mailBox MailBoxmailBox.Init()go func() {for i := 0; i < 5; i++ {go func(i int) {mailBox.Send(i) // wait 调用后, 其他的Send就可以获得锁了}(i)}}()time.Sleep(time.Second * 2)}
package mainimport ("fmt""sync""time")func main() {var locker sync.Mutexvar cond *sync.Cond = sync.NewCond(&locker)go func() {locker.Lock()defer locker.Unlock()time.Sleep(time.Second * 1)fmt.Println("1: wait...")cond.Wait()}()go func() {//cond2 := cond // 可以在 cond 使用前拷贝cond2 := *cond // 可以在 cond 使用前拷贝locker.Lock()defer locker.Unlock()time.Sleep(time.Second * 2)fmt.Println("2: wait...")cond2.Wait()}()time.Sleep(time.Second * 5)}
package mainimport ("fmt""sync""time")func main() {var locker sync.Mutexvar cond *sync.Cond = sync.NewCond(&locker)go func() {locker.Lock()defer locker.Unlock()time.Sleep(time.Second * 1)fmt.Println("1: wait...")cond.Wait()}()go func() {locker.Lock()defer locker.Unlock()time.Sleep(time.Second * 2)cond2 := cond // 在 cond 使用后拷贝指针的副本, 可以使用fmt.Println("2: wait...")cond2.Wait()}()time.Sleep(time.Second * 5)}
package mainimport ("fmt""sync""time")func main() {var locker sync.Mutexvar cond *sync.Cond = sync.NewCond(&locker)go func() {locker.Lock()defer locker.Unlock()time.Sleep(time.Second * 1)fmt.Println("1: wait...")cond.Wait()}()go func() {locker.Lock()defer locker.Unlock()time.Sleep(time.Second * 2)cond2 := *cond // 在 cond 使用后拷贝值的副本, 不可以使用fmt.Println("2: wait...")cond2.Wait() // panic: sync.Cond is copied}()time.Sleep(time.Second * 5)}