NOTE
2.10 sync.Cond
What sync.Cond is, Wait/Broadcast/Signal semantics, and a blocking-queue example using condition variables.
This is a historical learning note and may contain outdated or incomplete understanding.
1. What It Is
- A condition variable. The relationship between
LockerandCondis similar to the relationship betweenLockandConditionin Java. - All methods must be called while holding the Lock.
func NewCond(l Locker) *Condcreates a Cond using a Lock.func (c *Cond) Wait()automatically releases the Lock and pauses the current goroutine, blocking until it is awakened byBroadcast or Signal. It must be executed inside a while loop.func (c *Cond) Broadcast()wakes all goroutines blocked on the Cond.func (c *Cond) Signal()wakes any one goroutine blocked on the Cond.
2. Usage
type BlockingQueue struct {
lock sync.Locker
notFull *sync.Cond
notEmpty *sync.Cond
capacity int
items []string
}
func (c *BlockingQueue) Add(data string) {
c.lock.Lock()
defer c.lock.Unlock()
for len(c.items) == c.capacity {
c.notFull.Wait()
}
c.items = append(c.items, data)
c.notEmpty.Broadcast()
}
func (c *BlockingQueue) Remove() string {
c.lock.Lock()
defer c.lock.Unlock()
for len(c.items) == 0 {
c.notEmpty.Wait()
}
data := c.items[0]
c.items = c.items[1:]
c.notFull.Broadcast()
return data
}
func TestConcurrentList(t *testing.T) {
var mutex sync.Mutex
list := &BlockingQueue{
lock: &mutex,
notFull: sync.NewCond(&mutex),
notEmpty: sync.NewCond(&mutex),
capacity: 10,
items: make([]string, 0),
}
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
for i := 0; i < 1000; i++ {
list.Add(strconv.Itoa(i))
}
}()
go func() {
defer wg.Done()
for {
data := list.Remove()
fmt.Println(data)
if data == "999" {
break
}
}
}()
wg.Wait()
}
Discussion
Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub