- Wait():
- 把当前的 goroutine 加入当前条件变量的通知队列.
- 解锁当前条件变量基于的互斥锁. 所以 wait 前必须加锁.
- 当前 goroutine 阻塞在 wait()
- 通知到来并唤醒了当前 goroutine 后
- 解锁当前条件变量基于的互斥锁
- 执行后面的代码
- Signal()
- Broadcast
上代码, 自己品:
package main
import (
"fmt"
"sync"
"time"
)
type MailBox struct {
count uint8
locker sync.RWMutex
sendCond *sync.Cond
recvCond *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 = 1
self.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 = 0
self.sendCond.Signal()
}
func main() {
var mailBox MailBox
mailBox.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 main
import (
"fmt"
"sync"
"time"
)
type MailBox struct {
count uint8
locker sync.RWMutex
sendCond *sync.Cond
recvCond *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 = 1
self.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 = 0
self.sendCond.Signal()
}
func main() {
var mailBox MailBox
mailBox.Init()
go func() {
for i := 0; i < 5; i++ {
mailBox.Send(i) // Send 里面的 for 循环会阻塞
}
}()
time.Sleep(time.Second * 2)
}
/*
0
0 lock
0 Send
1
1 lock
1 Send wait...
*/
package main
import (
"fmt"
"sync"
"time"
)
type MailBox struct {
count uint8
locker sync.RWMutex
sendCond *sync.Cond
recvCond *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 = 1
self.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 = 0
self.sendCond.Signal()
}
func main() {
var mailBox MailBox
mailBox.Init()
go func() {
for i := 0; i < 5; i++ {
go func(i int) {
mailBox.Send(i) // wait 调用后, 其他的Send就可以获得锁了
}(i)
}
}()
time.Sleep(time.Second * 2)
}
/*
2
2 lock
2 Send
1
4
1 lock
1 Send wait...
0
0 lock
0 Send wait...
3
3 lock
3 Send wait...
4 lock
4 Send wait...
*/
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var locker sync.Mutex
var 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 main
import (
"fmt"
"sync"
"time"
)
func main() {
var locker sync.Mutex
var 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 main
import (
"fmt"
"sync"
"time"
)
func main() {
var locker sync.Mutex
var 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)
}