“Python/docs/3.9/library/asyncio-sync”的版本间差异
(autoload) |
小 (Page commit) |
||
第1行: | 第1行: | ||
+ | {{DISPLAYTITLE:同步原语 — Python 文档}} | ||
<div id="synchronization-primitives" class="section"> | <div id="synchronization-primitives" class="section"> | ||
<span id="asyncio-sync"></span> | <span id="asyncio-sync"></span> | ||
− | = | + | = 同步原语 = |
− | ''' | + | '''源代码:''' [[#id1|<span id="id2" class="problematic">:source:`Lib/asyncio/locks.py`</span>]] |
− | |||
− | |||
− | + | ----- | |
− | |||
− | asyncio | + | asyncio 同步原语被设计为类似于 [[../threading#module-threading|threading]] 模块的那些,但有两个重要的警告: |
+ | |||
+ | * asyncio 原语不是线程安全的,因此它们不应该用于 OS 线程同步(为此使用 [[../threading#module-threading|threading]]); | ||
+ | * 这些同步原语的方法不接受 ''timeout'' 参数; 使用 <code>asyncio.wait_for()</code> 函数执行超时操作。 | ||
+ | |||
+ | asyncio 具有以下基本同步原语: | ||
* [[#asyncio.Lock|<code>Lock</code>]] | * [[#asyncio.Lock|<code>Lock</code>]] | ||
第19行: | 第22行: | ||
* [[#asyncio.Semaphore|<code>Semaphore</code>]] | * [[#asyncio.Semaphore|<code>Semaphore</code>]] | ||
* [[#asyncio.BoundedSemaphore|<code>BoundedSemaphore</code>]] | * [[#asyncio.BoundedSemaphore|<code>BoundedSemaphore</code>]] | ||
+ | |||
+ | |||
+ | ----- | ||
<div id="lock" class="section"> | <div id="lock" class="section"> | ||
− | == | + | == 锁 == |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">asyncio.</span></span><span class="sig-name descname"><span class="pre">Lock</span></span><span class="sig-paren">(</span>''<span class="pre">\*</span>'', ''<span class="pre">loop=None</span>''<span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>为异步任务实现互斥锁。 不是线程安全的。</p> |
− | <p> | + | <p>异步锁可用于保证对共享资源的独占访问。</p> |
− | + | <p>使用 Lock 的首选方法是 [[../../reference/compound_stmts#async-with|async with]] 语句:</p> | |
− | <p> | ||
− | |||
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">lock = asyncio.Lock() |
# ... later | # ... later | ||
async with lock: | async with lock: | ||
− | # access shared state</ | + | # access shared state</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | <p> | + | <p>这相当于:</p> |
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">lock = asyncio.Lock() |
# ... later | # ... later | ||
第56行: | 第60行: | ||
# access shared state | # access shared state | ||
finally: | finally: | ||
− | lock.release()</ | + | lock.release()</syntaxhighlight> |
− | |||
− | |||
</div> | </div> | ||
− | |||
− | |||
− | |||
</div> | </div> | ||
<dl> | <dl> | ||
− | <dt | + | <dt><span class="sig-name descname"><span class="pre">release</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt> |
− | + | <dd><p>释放锁。</p> | |
− | + | <p>当锁定为''locked''时,将其重置为''unlocked''并返回。</p> | |
− | + | <p>如果锁是 ''unlocked'',则会引发 [[../exceptions#RuntimeError|RuntimeError]]。</p></dd></dl> | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | <dd><p> | ||
− | <p> | ||
− | <p> | ||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">locked</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>如果锁是 ''locked'',则返回 <code>True</code>。</p></dd></dl> |
</dd></dl> | </dd></dl> | ||
第92行: | 第80行: | ||
<div id="event" class="section"> | <div id="event" class="section"> | ||
− | == | + | == 事件 == |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">asyncio.</span></span><span class="sig-name descname"><span class="pre">Event</span></span><span class="sig-paren">(</span>''<span class="pre">\*</span>'', ''<span class="pre">loop=None</span>''<span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>一个事件对象。 不是线程安全的。</p> |
− | <p> | + | <p>一个 asyncio 事件可用于通知多个 asyncio 任务某个事件已经发生。</p> |
− | + | <p>事件对象管理一个内部标志,可以使用 [[#asyncio.Event.set|set()]] 方法将其设置为 ''true'',并使用 clear()[ 重置为 ''false''[ X153X] 方法。 <code>wait()</code> 方法阻塞,直到标志设置为 ''true''。 该标志最初设置为 ''false''。</p> | |
− | <p> | + | <p>例子:</p> |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | <p> | ||
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">async def waiter(event): |
print('waiting for it ...') | print('waiting for it ...') | ||
await event.wait() | await event.wait() | ||
第132行: | 第111行: | ||
await waiter_task | await waiter_task | ||
− | asyncio.run(main())</ | + | asyncio.run(main())</syntaxhighlight> |
</div> | </div> | ||
第138行: | 第117行: | ||
</div> | </div> | ||
<dl> | <dl> | ||
− | <dt | + | <dt><span class="sig-name descname"><span class="pre">set</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt> |
− | + | <dd><p>设置事件。</p> | |
− | + | <p>所有等待事件设置的任务将立即被唤醒。</p></dd></dl> | |
− | |||
− | |||
− | |||
− | |||
− | <dd><p> | ||
− | <p> | ||
− | |||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">clear</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>清除(取消设置)事件。</p> |
− | <p> | + | <p>在 <code>wait()</code> 上等待的任务现在将阻塞,直到再次调用 [[#asyncio.Event.set|set()]] 方法。</p></dd></dl> |
− | [[.. | ||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">is_set</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>如果设置了事件,则返回 <code>True</code>。</p></dd></dl> |
</dd></dl> | </dd></dl> | ||
第164行: | 第135行: | ||
<div id="condition" class="section"> | <div id="condition" class="section"> | ||
− | == | + | == 状况 == |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">asyncio.</span></span><span class="sig-name descname"><span class="pre">Condition</span></span><span class="sig-paren">(</span>''<span class="pre">lock=None</span>'', ''<span class="pre">\*</span>'', ''<span class="pre">loop=None</span>''<span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>一个条件对象。 不是线程安全的。</p> |
− | <p> | + | <p>任务可以使用异步条件原语来等待某个事件发生,然后获得对共享资源的独占访问权限。</p> |
− | + | <p>本质上,Condition 对象结合了 [[#asyncio.Event|Event]] 和 [[#asyncio.Lock|Lock]] 的功能。 可以让多个 Condition 对象共享一个 Lock,这允许在对共享资源的特定状态感兴趣的不同任务之间协调对共享资源的独占访问。</p> | |
− | + | <p>可选的 ''lock'' 参数必须是 [[#asyncio.Lock|Lock]] 对象或 <code>None</code>。 在后一种情况下,会自动创建一个新的 Lock 对象。</p> | |
− | <p> | + | <p>使用条件的首选方法是 [[../../reference/compound_stmts#async-with|async with]] 语句:</p> |
− | |||
− | |||
− | |||
− | |||
− | <p> | ||
− | <code>None</code> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | <p> | ||
− | |||
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">cond = asyncio.Condition() |
# ... later | # ... later | ||
async with cond: | async with cond: | ||
− | await cond.wait()</ | + | await cond.wait()</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | <p> | + | <p>这相当于:</p> |
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">cond = asyncio.Condition() |
# ... later | # ... later | ||
第212行: | 第169行: | ||
await cond.wait() | await cond.wait() | ||
finally: | finally: | ||
− | cond.release()</ | + | cond.release()</syntaxhighlight> |
</div> | </div> | ||
第218行: | 第175行: | ||
</div> | </div> | ||
<dl> | <dl> | ||
− | <dt | + | <dt><span class="sig-name descname"><span class="pre">notify</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">n</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">1</span></span>''<span class="sig-paren">)</span></dt> |
− | + | <dd><p>在此条件下最多唤醒 ''n'' 个任务(默认为 1 个)。 如果没有任务在等待,则该方法为空操作。</p> | |
− | + | <p>必须在调用此方法之前获取锁,并在不久之后释放锁。 如果使用 ''unlocked'' 锁调用,则会引发 [[../exceptions#RuntimeError|RuntimeError]] 错误。</p></dd></dl> | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | <dd><p> | ||
− | <p> | ||
− | |||
− | |||
− | |||
− | |||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">locked</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>如果获取了底层锁,则返回 <code>True</code>。</p></dd></dl> |
− | |||
− | |||
<dl> | <dl> | ||
− | <dt> | + | <dt><span class="sig-name descname"><span class="pre">notify_all</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>唤醒所有在此条件下等待的任务。</p> |
− | <p> | + | <p>此方法的作用类似于 [[#asyncio.Condition.notify|notify()]],但会唤醒所有等待的任务。</p> |
− | + | <p>必须在调用此方法之前获取锁,并在不久之后释放锁。 如果使用 ''unlocked'' 锁调用,则会引发 [[../exceptions#RuntimeError|RuntimeError]] 错误。</p></dd></dl> | |
− | <p> | ||
− | |||
− | |||
− | |||
<dl> | <dl> | ||
− | <dt> | + | <dt><span class="sig-name descname"><span class="pre">release</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>释放底层锁。</p> |
− | <p> | + | <p>当在解锁的锁上调用时,会引发 [[../exceptions#RuntimeError|RuntimeError]]。</p></dd></dl> |
− | |||
− | |||
</dd></dl> | </dd></dl> | ||
第272行: | 第199行: | ||
<div id="semaphore" class="section"> | <div id="semaphore" class="section"> | ||
− | == | + | == 信号 == |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">asyncio.</span></span><span class="sig-name descname"><span class="pre">Semaphore</span></span><span class="sig-paren">(</span>''<span class="pre">value=1</span>'', ''<span class="pre">\*</span>'', ''<span class="pre">loop=None</span>''<span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>一个信号量对象。 不是线程安全的。</p> |
− | <p> | + | <p>信号量管理一个内部计数器,该计数器由每个 <code>acquire()</code> 调用递减,并由每个 [[#asyncio.Semaphore.release|release()]] 调用递增。 计数器永远不会低于零; 当 <code>acquire()</code> 发现它为零时,它会阻塞,直到某个任务调用 [[#asyncio.Semaphore.release|release()]]。</p> |
− | + | <p>可选的 ''value'' 参数给出内部计数器的初始值(默认为 <code>1</code>)。 如果给定值小于 <code>0</code>,则会引发 [[../exceptions#ValueError|ValueError]]。</p> | |
− | + | <p>使用信号量的首选方法是 [[../../reference/compound_stmts#async-with|async with]] 语句:</p> | |
− | |||
− | [[#asyncio.Semaphore.release| | ||
− | <p> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | <p> | ||
− | |||
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">sem = asyncio.Semaphore(10) |
# ... later | # ... later | ||
async with sem: | async with sem: | ||
− | # work with shared resource</ | + | # work with shared resource</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | <p> | + | <p>这相当于:</p> |
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">sem = asyncio.Semaphore(10) |
# ... later | # ... later | ||
第317行: | 第232行: | ||
# work with shared resource | # work with shared resource | ||
finally: | finally: | ||
− | sem.release()</ | + | sem.release()</syntaxhighlight> |
</div> | </div> | ||
第323行: | 第238行: | ||
</div> | </div> | ||
<dl> | <dl> | ||
− | <dt | + | <dt><span class="sig-name descname"><span class="pre">locked</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt> |
− | + | <dd><p>如果不能立即获取信号量,则返回 <code>True</code>。</p></dd></dl> | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | <dd><p> | ||
<dl> | <dl> | ||
− | <dt>< | + | <dt><span class="sig-name descname"><span class="pre">release</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>释放信号量,将内部计数器加一。 可以唤醒一个等待获取信号量的任务。</p> |
− | + | <p>与 [[#asyncio.BoundedSemaphore|BoundedSemaphore]] 不同,[[#asyncio.Semaphore|Semaphore]] 允许进行比 <code>acquire()</code> 调用更多的 <code>release()</code> 调用。</p></dd></dl> | |
− | <p> | ||
− | |||
</dd></dl> | </dd></dl> | ||
第345行: | 第251行: | ||
<div id="boundedsemaphore" class="section"> | <div id="boundedsemaphore" class="section"> | ||
− | == | + | == 有界信号量 == |
<dl> | <dl> | ||
− | <dt>''class'' < | + | <dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">asyncio.</span></span><span class="sig-name descname"><span class="pre">BoundedSemaphore</span></span><span class="sig-paren">(</span>''<span class="pre">value=1</span>'', ''<span class="pre">\*</span>'', ''<span class="pre">loop=None</span>''<span class="sig-paren">)</span></dt> |
− | <dd><p> | + | <dd><p>有界信号量对象。 不是线程安全的。</p> |
− | <p> | + | <p>有界信号量是 [[#asyncio.Semaphore|Semaphore]] 的一个版本,如果将内部计数器增加到初始 ''值'' 以上,则会在 [[#asyncio.Semaphore.release|release()]] 中引发 [[../exceptions#ValueError|ValueError]]。</p></dd></dl> |
− | |||
− | |||
− | < | ||
− | |||
− | + | ----- | |
<div class="versionchanged"> | <div class="versionchanged"> | ||
− | <span class="versionmodified changed"> | + | <span class="versionmodified changed">3.9 版更改:</span>使用 <code>await lock</code> 或 <code>yield from lock</code> 和/或 [[../../reference/compound_stmts#with|with]] 语句获取锁(<code>with await lock</code>,<code>with (yield from lock)</code>) 被移除。 请改用 <code>async with lock</code>。 |
− | [[../../reference/compound_stmts#with| | + | |
+ | </div> | ||
</div> | </div> | ||
</div> | </div> | ||
+ | <div class="clearer"> | ||
+ | |||
+ | |||
</div> | </div> | ||
− | [[Category:Python 3.9 | + | [[Category:Python 3.9 文档]] |
2021年10月31日 (日) 04:51的最新版本
同步原语
源代码: :source:`Lib/asyncio/locks.py`
asyncio 同步原语被设计为类似于 threading 模块的那些,但有两个重要的警告:
- asyncio 原语不是线程安全的,因此它们不应该用于 OS 线程同步(为此使用 threading);
- 这些同步原语的方法不接受 timeout 参数; 使用
asyncio.wait_for()
函数执行超时操作。
asyncio 具有以下基本同步原语:
锁
- class asyncio.Lock(\*, loop=None)
为异步任务实现互斥锁。 不是线程安全的。
异步锁可用于保证对共享资源的独占访问。
使用 Lock 的首选方法是 async with 语句:
这相当于:
- release()
释放锁。
当锁定为locked时,将其重置为unlocked并返回。
如果锁是 unlocked,则会引发 RuntimeError。
- locked()
如果锁是 locked,则返回
True
。
事件
- class asyncio.Event(\*, loop=None)
一个事件对象。 不是线程安全的。
一个 asyncio 事件可用于通知多个 asyncio 任务某个事件已经发生。
事件对象管理一个内部标志,可以使用 set() 方法将其设置为 true,并使用 clear()[ 重置为 false[ X153X] 方法。
wait()
方法阻塞,直到标志设置为 true。 该标志最初设置为 false。例子:
- set()
设置事件。
所有等待事件设置的任务将立即被唤醒。
- clear()
清除(取消设置)事件。
在
wait()
上等待的任务现在将阻塞,直到再次调用 set() 方法。
- is_set()
如果设置了事件,则返回
True
。
状况
- class asyncio.Condition(lock=None, \*, loop=None)
一个条件对象。 不是线程安全的。
任务可以使用异步条件原语来等待某个事件发生,然后获得对共享资源的独占访问权限。
本质上,Condition 对象结合了 Event 和 Lock 的功能。 可以让多个 Condition 对象共享一个 Lock,这允许在对共享资源的特定状态感兴趣的不同任务之间协调对共享资源的独占访问。
可选的 lock 参数必须是 Lock 对象或
None
。 在后一种情况下,会自动创建一个新的 Lock 对象。使用条件的首选方法是 async with 语句:
这相当于:
- notify(n=1)
在此条件下最多唤醒 n 个任务(默认为 1 个)。 如果没有任务在等待,则该方法为空操作。
必须在调用此方法之前获取锁,并在不久之后释放锁。 如果使用 unlocked 锁调用,则会引发 RuntimeError 错误。
- locked()
如果获取了底层锁,则返回
True
。
- notify_all()
唤醒所有在此条件下等待的任务。
此方法的作用类似于 notify(),但会唤醒所有等待的任务。
必须在调用此方法之前获取锁,并在不久之后释放锁。 如果使用 unlocked 锁调用,则会引发 RuntimeError 错误。
- release()
释放底层锁。
当在解锁的锁上调用时,会引发 RuntimeError。
信号
- class asyncio.Semaphore(value=1, \*, loop=None)
一个信号量对象。 不是线程安全的。
信号量管理一个内部计数器,该计数器由每个
acquire()
调用递减,并由每个 release() 调用递增。 计数器永远不会低于零; 当acquire()
发现它为零时,它会阻塞,直到某个任务调用 release()。可选的 value 参数给出内部计数器的初始值(默认为
1
)。 如果给定值小于0
,则会引发 ValueError。使用信号量的首选方法是 async with 语句:
这相当于:
- locked()
如果不能立即获取信号量,则返回
True
。
- release()
释放信号量,将内部计数器加一。 可以唤醒一个等待获取信号量的任务。
与 BoundedSemaphore 不同,Semaphore 允许进行比
acquire()
调用更多的release()
调用。
有界信号量
- class asyncio.BoundedSemaphore(value=1, \*, loop=None)
有界信号量对象。 不是线程安全的。
有界信号量是 Semaphore 的一个版本,如果将内部计数器增加到初始 值 以上,则会在 release() 中引发 ValueError。
3.9 版更改:使用 await lock
或 yield from lock
和/或 with 语句获取锁(with await lock
,with (yield from lock)
) 被移除。 请改用 async with lock
。