- By definition,
event
is any signal between two or moregoroutine
that actually occurred. Usually you will want one to wait for a signal before executing another goroutine. If we consider to do this without usingCond
then simply use an endless loop.
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> |
- This workaround is also good, but really won’t work, because you have to figure out how long it takes to configure the
sleep
function. If sleep is too long, it will affect performance, and if it is too short, it will wasteCPU
time unnecessarily. It would be nice if there was some kind of function or something wheregoroutine
couldsleep
until a signal executes. AndCond
will help enforce that.
functions in 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> |
- Signals:
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> |
- Use
Cond
to write a simple example first:
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> |
- This approach is more efficient. Note, the
Wait
func not only blocks, it also suspends the currentgoroutine
, and allows other goroutines to still run onOS thread
. - For further explanation, see also the following example:
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] |
- As a result, the program has added 10 items to the queue, but it always waits for one item to be
dequeue
beforeenqueue
another item. - In the example there is a
Signal
function, which is a method that Cond provides to notify a goroutine that was blocked on a previous wait.