- theo định nghĩa,
event
là bất kì tính hiệu nào giữa 2 hoặc nhiềugoroutine
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ùngCond
thì đơn giản là dùng vòng lặp vô tận.
1 2 3 4 | <span class="token keyword">for</span> <span class="token function">conditionTrue</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token boolean">false</span> <span class="token punctuation">{</span> time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token operator">*</span>time<span class="token punctuation">.</span>Millisecond<span class="token punctuation">)</span> <span class="token punctuation">}</span> |
- 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ủaCPU
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:
- NewCond:
1 2 | <span class="token keyword">func</span> <span class="token function">NewCond</span><span class="token punctuation">(</span>l Locker<span class="token punctuation">)</span> <span class="token operator">*</span>Cond <span class="token comment">// Create a new Cond conditional variable.</span> |
- Broadcast
1 2 3 4 | <span class="token keyword">func</span> <span class="token punctuation">(</span>c <span class="token operator">*</span>Cond<span class="token punctuation">)</span> <span class="token function">Broadcast</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// Broadcast will wake up all goroutines waiting for c.</span> <span class="token comment">// Broadcast can be called with or without locking.</span> |
- Signal:
1 2 3 4 | <span class="token keyword">func</span> <span class="token punctuation">(</span>c <span class="token operator">*</span>Cond<span class="token punctuation">)</span> <span class="token function">Signal</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// Signal wakes up only 1 goroutine waiting for c.</span> <span class="token comment">// Signal can be called with or without locking.</span> |
- Wait:
1 2 3 | <span class="token keyword">func</span> <span class="token punctuation">(</span>c <span class="token operator">*</span>Cond<span class="token punctuation">)</span> <span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// does not return unless it is woken up by Signal or Broadcast.</span> |
- Sử dụng
Cond
để viết một ví dụ đơn giản trước:
1 2 3 4 5 6 7 | c <span class="token operator">:=</span> sync<span class="token punctuation">.</span><span class="token function">NewCond</span><span class="token punctuation">(</span><span class="token operator">&</span>sync<span class="token punctuation">.</span>Mutex<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token comment">// (1) new cond instantiate, func NewCond sẽ đáp ứng sync.Locker</span> c<span class="token punctuation">.</span>L<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// (2) Lock process</span> <span class="token keyword">for</span> <span class="token function">conditionTrue</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token boolean">false</span> <span class="token punctuation">{</span> c<span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// (3) chúng ta sẽ đợi khi có một thông báo điều kiện được xả ra. Và sẽ block tất cả các goroutine khác.</span> <span class="token punctuation">}</span> c<span class="token punctuation">.</span>L<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// (4) UnLock process</span> |
- 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 treogoroutine
hiện tại, và cho phép các goroutine khác vẫn chạy trênOS thread
. - Để giải thích thêm, xem thêm ví dụ sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <span class="token keyword">func</span> <span class="token function">CondExample1</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> c <span class="token operator">:=</span> sync<span class="token punctuation">.</span><span class="token function">NewCond</span><span class="token punctuation">(</span><span class="token operator">&</span>sync<span class="token punctuation">.</span>Mutex<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> queue <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> removeFromQueue <span class="token operator">:=</span> <span class="token keyword">func</span><span class="token punctuation">(</span>delay time<span class="token punctuation">.</span>Duration<span class="token punctuation">,</span> i <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>delay<span class="token punctuation">)</span> c<span class="token punctuation">.</span>L<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"before remove:"</span><span class="token punctuation">,</span> queue<span class="token punctuation">)</span> queue <span class="token operator">=</span> queue<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">:</span><span class="token punctuation">]</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"after remove:"</span><span class="token punctuation">,</span> queue<span class="token punctuation">)</span> c<span class="token punctuation">.</span>L<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> c<span class="token punctuation">.</span><span class="token function">Signal</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"start loop;"</span><span class="token punctuation">,</span> i<span class="token punctuation">)</span> c<span class="token punctuation">.</span>L<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">for</span> <span class="token function">len</span><span class="token punctuation">(</span>queue<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">2</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"len equal 2, waiting"</span><span class="token punctuation">,</span> i<span class="token punctuation">)</span> c<span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"Adding to queue"</span><span class="token punctuation">,</span> i<span class="token punctuation">)</span> queue <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>queue<span class="token punctuation">,</span> i<span class="token punctuation">)</span> <span class="token keyword">go</span> <span class="token function">removeFromQueue</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token operator">*</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">,</span> i<span class="token punctuation">)</span> c<span class="token punctuation">.</span>L<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"after processing, len queue:"</span><span class="token punctuation">,</span> <span class="token function">len</span><span class="token punctuation">(</span>queue<span class="token punctuation">)</span><span class="token punctuation">,</span> queue<span class="token punctuation">)</span> <span class="token punctuation">}</span> |
- output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | 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 khienqueue
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 đó.