title: Does the lock in asyncio.Condition have other purpose besides compatibility with threading.Condition?
body: <p>I'd like to ask about <a href="https://docs.python.org/3/library/asyncio-sync.html#condition" rel="noreferrer">asyncio.Condition</a>. I'm not familiar with the concept, but I know and understand locks, semaphores, and queues since my student years.</p>
  
  <p>I could not find a good explanation or typical use cases, just <a href="https://pymotw.com/3/asyncio/synchronization.html" rel="noreferrer">this example</a>. I looked at the source. The core fnctionality is achieved with a FIFO of futures. Each waiting coroutine adds a new future and awaits it. Another coroutine may call <code>notify()</code> which sets the result of one or optionally more futures from the FIFO and that wakes up the same number of waiting coroutines. Really simple up to this point.</p>
  
  <p>However, the implementation and the usage is more complicated than this. A waiting coroutine must first acquire a lock associated with the condition in order to be able to wait (and the <code>wait()</code> releases it while waiting). Also the notifier must acquire a lock to be able to notify(). This leads to <code>with</code> statement before each operation:</p>
  
  <pre><code>async with condition:
      # condition operation (wait or notify)
  </code></pre>
  
  <p>or else a <code>RuntimeError</code> occurrs.</p>
  
  <p>I do not understand the point of having this lock. What resource do we need to protect with the lock? In asyncio there could be always only one coroutine executing in the event loop, there are no "critical sections" as known from threading. </p>
  
  <p>Is this lock really needed (why?) or is it for compatibility with threading code only?</p>
  
  <p>My first idea was it is for the compatibility, but in such case why didn't they remove the lock while preserving the usage? i.e. making</p>
  
  <pre><code>async with condition:
  </code></pre>
  
  <p>basically an optional no-op.</p>