Semaphore和BoundedSemaphore
Semaphore和BoundedSemaphore

Semaphore和BoundedSemaphore

概述

在Python的asyncio模块中,Semaphore(信号量)和BoundedSemaphore(有界信号量)都用于控制在异步编程中对共享资源的访问。它们通过限制同时可以访问共享资源的协程数量来管理并发。

  1. Semaphore(信号量)

    • Semaphoreasyncio中的一个计数器,用于跟踪允许访问共享资源的任务数量。当计数器为正时,允许访问资源;当计数器为零时,资源被锁定,其他任务需要等待释放资源后才能访问。Semaphore的计数器在初始化时被设置为一个非负整数。当计数器为1时,Semaphore行为类似于Lock(锁),即只允许一个任务访问资源;当计数器大于1时,允许多个任务同时访问资源。
  2. BoundedSemaphore(有界信号量)

    • BoundedSemaphoreasyncio中的一种特殊类型的Semaphore,它有一个上限值。与普通的Semaphore不同,BoundedSemaphore的计数器在初始化时被设置为一个非负整数,并且还有一个上限值。当计数器达到上限值时,任何尝试增加计数器的操作都会被阻塞,直到有其他任务释放了资源并将计数器降低。
      在Python的asyncio库中,Semaphore和BoundedSemaphore是用于控制异步任务访问共享资源或执行关键部分的同步原语。

Semaphore

Semaphore是一个通用的信号量,它可以有一个非负整数值,表示可用的“许可”数量。每次一个异步任务需要访问共享资源时,它会尝试获取一个许可;如果许可可用,任务会继续执行;如果没有许可可用,任务会等待,直到有许可可用。

你可以使用Semaphore来限制并发执行的任务数量,即使资源是无限的。

示例:

from asyncio import Semaphore, create_task, run  

sem = Semaphore(3)  # 最多允许3个任务同时执行  

async def worker():  
    async with sem:  
        # 执行某些操作  
        print(f"Worker is running, current semaphore value: {sem._value}")  

async def main():  
    tasks = [create_task(worker()) for _ in range(10)]  
    await asyncio.gather(*tasks)  

run(main())

BoundedSemaphore

BoundedSemaphore是Semaphore的一个特殊版本,它有一个固定的最大值,表示许可的总数。尝试创建一个超过其最大值的BoundedSemaphore会引发ValueError。

使用BoundedSemaphore可以确保你不会意外地创建过多的许可,这在某些场景中可能是有用的,例如,当你有一个固定数量的物理资源(如数据库连接)并且不想超出这个数量时。

示例:

from asyncio import BoundedSemaphore, create_task, run  

sem = BoundedSemaphore(3)  # 最多允许3个许可  

async def worker():  
    async with sem:  
        # 执行某些操作  
        print(f"Worker is running, current semaphore value: {sem._value}")  

async def main():  
    tasks = [create_task(worker()) for _ in range(10)]  
    await asyncio.gather(*tasks)  

run(main())

在这两个示例中,尽管我们创建了10个任务,但由于Semaphore或BoundedSemaphore的限制,最多只有3个任务可以同时执行。其他任务会等待,直到有任务完成并释放许可。

注意:在实际代码中,通常不建议直接访问_value属性来检查信号量的值,因为这是一个内部实现细节,并可能在未来的版本中发生变化。这里只是为了解释目的而使用。

发表回复

您的电子邮箱地址不会被公开。