- theo định nghĩa,
event
là bất kì tính hiệu nào giữa 2 hoặc nhiều goroutine
mà thực tế nó đã xảy ra. Thông thường bạn sẽ muốn một đợi một tính hiệu trước khi thực hiện một goroutine khác. Nếu chúng ta xem xét để thực hiện điều này mà ko dùng Cond
thì đơn giản là dùng vòng lặp vô tận.
for conditionTrue() == false { time.Sleep(1*time.Millisecond)
}
- Cách giải quyết này cũng tốt, nhưng thực sự là sẽ không hiệu quả, bời vì bạn phải tìm ra thời gian để cấu hình hàm
sleep
. Nếu sleep quá lâu thì sẽ ảnh hưởng đến performance, còn nếu quá ngắn sẽ thì sẽ tốn thời gian của CPU
một cách không cần thiết. Nó sẽ tốt nếu có một loại function hoặc cách gì đó mà goroutine
có thể sleep
cho đến khi có 1 tín hiệu thực thi. Và Cond
sẽ giúp thực thi điều đó.
các function trong cond:
func NewCond(l Locker) *Cond
func (c *Cond) Broadcast()
func (c *Cond) Signal()
func (c *Cond) Wait()
- Sử dụng
Cond
để viết một ví dụ đơn giản trước:
c := sync.NewCond(&sync.Mutex{})
c.L.Lock()
for conditionTrue() == false { c.Wait()
}
c.L.Unlock()
- Cách tiếp cận này là hiệu quả hơn. Ghi chú, func
Wait
không chỉ block, nó còn treo goroutine
hiện tại, và cho phép các goroutine khác vẫn chạy trên OS thread
.
- Để giải thích thêm, xem thêm ví dụ sau:
func CondExample1() { c := sync.NewCond(&sync.Mutex{}) queue := make([]int, 0, 10) removeFromQueue := func(delay time.Duration, i int) { time.Sleep(delay) c.L.Lock() fmt.Println("before remove:", queue) queue = queue[1:] fmt.Println("after remove:", queue) c.L.Unlock() c.Signal() } for i := 0; i < 10; i++ { fmt.Println("start loop;", i) c.L.Lock() for len(queue) == 2 { fmt.Println("len equal 2, waiting", i) c.Wait() } fmt.Println("Adding to queue", i) queue = append(queue, i) go removeFromQueue(1*time.Second, i) c.L.Unlock() fmt.Println() } fmt.Println("after processing, len queue:", len(queue), queue)
}
start loop; 0
Adding to queue 0 start loop; 1
Adding to queue 1 start loop; 2
len equal 2, waiting 2
before remove: [0 1]
after remove: [1]
Adding to queue 2 start loop; 3
len equal 2, waiting 3
before remove: [1 2]
after remove: [2]
Adding to queue 3 start loop; 4
len equal 2, waiting 4
before remove: [2 3]
after remove: [3]
Adding to queue 4 start loop; 5
len equal 2, waiting 5
before remove: [3 4]
after remove: [4]
Adding to queue 5 start loop; 6
len equal 2, waiting 6
before remove: [4 5]
after remove: [5]
Adding to queue 6 start loop; 7
before remove: [5 6]
after remove: [6]
Adding to queue 7 start loop; 8
len equal 2, waiting 8
before remove: [6 7]
after remove: [7]
Adding to queue 8 start loop; 9
len equal 2, waiting 9
before remove: [7 8]
after remove: [8]
Adding to queue 9 after processing, len queue: 2 [8 9]
- Như kết quả, thì chương trình đã add 10 item đến queue, nhưng nó luôn luôn đợi cho cho 1 item được
dequeue
trước khi enqueue
một item khác
- Trong ví dụ có một function
Signal
, nó là một method mà Cond cung cấp để notifying một goroutine đã được block trên wait trước đó.