同步原语
********

**源代码:** Lib/asyncio/locks.py

======================================================================

asyncio 同步原语被设计为与 "threading" 模块的类似，但有两个关键注意事
项:

* asyncio 原语不是线程安全的，因此它们不应被用于 OS 线程同步 (而应当使
  用 "threading")；

* 这些同步原语的方法不接受 *timeout* 参数；请使用 "asyncio.wait_for()"
  函数来执行带有超时的操作。

asyncio 具有下列基本同步原语:

* "Lock"

* "Event"

* "Condition"

* "Semaphore"

* "BoundedSemaphore"

======================================================================


Lock
====

class asyncio.Lock(*, loop=None)

   实现一个用于 asyncio 任务的互斥锁。 非线程安全。

   asyncio 锁可被用来保证对共享资源的独占访问。

   使用 Lock 的推荐方式是通过 "async with" 语句:

      lock = asyncio.Lock()

      # ... later
      async with lock:
          # access shared state

   这等价于:

      lock = asyncio.Lock()

      # ... later
      await lock.acquire()
      try:
          # access shared state
      finally:
          lock.release()

   Deprecated since version 3.8, will be removed in version 3.10:
   *loop* 形参。

   coroutine acquire()

      获取锁。

      此方法会等待直至锁为 *unlocked*，将其设为 *locked* 并返回 "True"
      。

      当有一个以上的协程在 "acquire()" 中被阻塞则会等待解锁，最终只有
      一个协程会被执行。

      锁的获取是 *公平的*: 被执行的协程将是第一个开始等待锁的协程。

   release()

      释放锁。

      当锁为 *locked* 时，将其设为 *unlocked* 并返回。

      如果锁为 *unlocked*，则会引发 "RuntimeError"。

   locked()

      如果锁为 *locked* 则返回 "True"。


Event
=====

class asyncio.Event(*, loop=None)

   事件对象。 该对象不是线程安全的。

   asyncio 事件可被用来通知多个 asyncio 任务已经有事件发生。

   Event 对象会管理一个内部旗标，可通过 "set()" 方法将其设为 *true* 并
   通过 "clear()" 方法将其重设为 *false*。 "wait()" 方法会阻塞直至该旗
   标被设为 *true*。 该旗标初始时会被设为 *false*。

   Deprecated since version 3.8, will be removed in version 3.10:
   *loop* 形参。

   示例:

      async def waiter(event):
          print('waiting for it ...')
          await event.wait()
          print('... got it!')

      async def main():
          # Create an Event object.
          event = asyncio.Event()

          # Spawn a Task to wait until 'event' is set.
          waiter_task = asyncio.create_task(waiter(event))

          # Sleep for 1 second and set the event.
          await asyncio.sleep(1)
          event.set()

          # Wait until the waiter task is finished.
          await waiter_task

      asyncio.run(main())

   coroutine wait()

      等待直至事件被设置。

      如果事件已被设置，则立即返回 "True"。 否则将阻塞直至另一个任务调
      用 "set()"。

   set()

      设置事件。

      所有等待事件被设置的任务将被立即唤醒。

   clear()

      清空（取消设置）事件。

      通过 "wait()" 进行等待的任务现在将会阻塞直至 "set()" 方法被再次
      调用。

   is_set()

      如果事件已被设置则返回 "True"。


Condition
=========

class asyncio.Condition(lock=None, *, loop=None)

   条件对象。 该对象不是线程安全的。

   asyncio 条件原语可被任务用于等待某个事件发生，然后获取对共享资源的
   独占访问。

   在本质上，Condition 对象合并了 "Event" 和 "Lock" 的功能。 多个
   Condition 对象有可能共享一个 Lock，这允许关注于共享资源的特定状态的
   不同任务实现对共享资源的协同独占访问。

   可选的 *lock* 参数必须为 "Lock" 对象或 "None"。 在后一种情况下会自
   动创建一个新的 Lock 对象。

   Deprecated since version 3.8, will be removed in version 3.10:
   *loop* 形参。

   使用 Condition 的推荐方式是通过 "async with" 语句:

      cond = asyncio.Condition()

      # ... later
      async with cond:
          await cond.wait()

   这等价于:

      cond = asyncio.Condition()

      # ... later
      await cond.acquire()
      try:
          await cond.wait()
      finally:
          cond.release()

   coroutine acquire()

      获取下层的锁。

      此方法会等待直至下层的锁为 *unlocked*，将其设为 *locked* 并返回
      returns "True"。

   notify(n=1)

      唤醒最多 *n* 个正在等待此条件的任务（默认为 1 个）。 如果没有任
      务正在等待则此方法为空操作。

      锁必须在此方法被调用前被获取并在随后被快速释放。 如果通过一个
      *unlocked* 锁调用则会引发 "RuntimeError"。

   locked()

      如果下层的锁已被获取则返回 "True"。

   notify_all()

      唤醒所有正在等待此条件的任务。

      此方法的行为类似于 "notify()"，但会唤醒所有正在等待的任务。

      锁必须在此方法被调用前被获取并在随后被快速释放。 如果通过一个
      *unlocked* 锁调用则会引发 "RuntimeError"。

   release()

      释放下层的锁。

      当在未锁定的锁上发起调用时，会引发 "RuntimeError"。

   coroutine wait()

      等待直至收到通知。

      当此方法被调用时如果调用方任务未获得锁，则会引发 "RuntimeError"
      。

      这个方法会释放下层的锁，然后保持阻塞直到被 "notify()" 或
      "notify_all()" 调用所唤醒。 一旦被唤醒，Condition 会重新获取它的
      锁并且此方法将返回 "True"。

   coroutine wait_for(predicate)

      等待直到目标值变为 *true*。

      目标必须为一个可调用对象，其结果将被解读为一个布尔值。 最终的值
      将为返回值。


Semaphore
=========

class asyncio.Semaphore(value=1, *, loop=None)

   信号量对象。 该对象不是线程安全的。

   信号量会管理一个内部计数器，该计数器会随每次 "acquire()" 调用递减并
   随每次 "release()" 调用递增。 计数器的值永远不会降到零以下；当
   "acquire()" 发现其值为零时，它将保持阻塞直到有某个任务调用了
   "release()"。

   可选的 *value* 参数用来为内部计数器赋初始值 (默认值为 "1")。 如果给
   定的值小于 "0" 则会引发 "ValueError"。

   Deprecated since version 3.8, will be removed in version 3.10:
   *loop* 形参。

   使用 Semaphore 的推荐方式是通过 "async with" 语句。:

      sem = asyncio.Semaphore(10)

      # ... later
      async with sem:
          # work with shared resource

   这等价于:

      sem = asyncio.Semaphore(10)

      # ... later
      await sem.acquire()
      try:
          # work with shared resource
      finally:
          sem.release()

   coroutine acquire()

      获取一个信号量。

      如果内部计数器的值大于零，则将其减一并立即返回 "True"。 如果其值
      为零，则会等待直到 "release()" 并调用并返回 "True"。

   locked()

      如果信号量对象无法被立即获取则返回 "True"。

   release()

      释放一个信号量对象，将内部计数器的值加一。 可以唤醒一个正在等待
      获取信号量对象的任务。

      不同于 "BoundedSemaphore"，"Semaphore" 允许执行的 "release()" 调
      用多于 "acquire()" 调用。


BoundedSemaphore
================

class asyncio.BoundedSemaphore(value=1, *, loop=None)

   绑定的信号量对象。 该对象不是线程安全的。

   BoundedSemaphore 是特殊版本的 "Semaphore"，如果在 "release()" 中内
   部计数器值增加到初始 *value* 以上它将引发一个 "ValueError"。

   Deprecated since version 3.8, will be removed in version 3.10:
   *loop* 形参。

======================================================================

3.9 版更變: 使用 "await lock" 或 "yield from lock" 以及/或者 "with" 语
句 ("with await lock", "with (yield from lock)") 来获取锁的操作已被移
除。 请改用 "async with lock"。
