package study
import (
"container/list"
"fmt"
"sync"
"testing"
"time"
)
var (
lock = new(sync.Mutex)
cond = sync.NewCond(lock)
queue = NewQueue(5)
done = make(chan bool)
)
type Product struct {
Data string
}
type Queue struct {
l *list.List
Cap int
}
func NewQueue(capacity int) *Queue {
return &Queue{l: list.New(), Cap: capacity}
}
func (q *Queue) Put(p *Product) {
q.l.PushBack(p)
}
func (q *Queue) Take() *Product {
t := q.l.Front()
defer q.l.Remove(t)
return t.Value.(*Product)
}
func (q *Queue) IsEmpty() bool {
return q.l.Len() == 0
}
func (q *Queue) IsFull() bool {
return q.l.Len() == q.Cap
}
func TestCond(t *testing.T) {
for i := 0; i < 3; i++ {
go func(i int) {
for {
lock.Lock()
fmt.Println("消费者上锁")
for queue.IsEmpty() {
fmt.Println("消费者解锁 waite")
cond.Wait()
fmt.Println("消费者上锁")
}
fmt.Printf("消费者[%d]:%s\n", i, queue.Take().Data)
cond.Signal()
fmt.Println("消费者通知生产者")
time.Sleep(5 * time.Second)
fmt.Println("消费者解锁")
lock.Unlock()
}
}(i)
}
for i := 0; i < 5; i++ {
go func(i int) {
for {
lock.Lock()
fmt.Println("生产者上锁")
for queue.IsFull() {
fmt.Println("生产者解锁 waite")
cond.Wait()
fmt.Println("生产者上锁")
}
fmt.Printf("生产者[%d]\n", i)
queue.Put(&Product{Data: "hello, world"})
cond.Signal()
fmt.Println("生产者通知消费者")
time.Sleep(5 * time.Second)
fmt.Println("生产者解锁")
lock.Unlock()
time.Sleep(1 * time.Second)
}
}(i)
}
<-done
}
func TestCondQueue(t *testing.T) {
mutex := sync.Mutex{}
var cond = sync.NewCond(&mutex)
mail := 1
go func() {
for count := 0; count <= 15; count++ {
time.Sleep(time.Second)
mail = count
cond.Broadcast()
}
}()
go func() {
for mail != 5 {
cond.L.Lock()
cond.Wait()
time.Sleep(5 * time.Second)
fmt.Println("持有锁 worker1")
fmt.Println(mail)
cond.L.Unlock()
}
fmt.Println("worker1 started to work")
time.Sleep(3 * time.Second)
fmt.Println("worker1 work end")
}()
go func() {
for mail != 10 {
cond.L.Lock()
cond.Wait()
time.Sleep(5 * time.Second)
fmt.Println("持有锁 worker2")
fmt.Println(mail)
cond.L.Unlock()
}
fmt.Println("worker2 started to work")
time.Sleep(3 * time.Second)
fmt.Println("worker2 work end")
}()
go func() {
for mail != 10 {
cond.L.Lock()
cond.Wait()
time.Sleep(5 * time.Second)
fmt.Println("持有锁 worker3")
fmt.Println(mail)
cond.L.Unlock()
}
fmt.Println("worker3 started to work")
time.Sleep(3 * time.Second)
fmt.Println("worker3 work end")
}()
select {}
}