import asyncio
   async def access_resource(semaphore, resource_id):
       async with semaphore:
           print(f"Resource {resource_id} acquired.")
           await asyncio.sleep(1)  # Имитация работы с ресурсом
           print(f"Resource {resource_id} released.")
   async def main():
       semaphore = asyncio.Semaphore(2)  # Ограничиваем до 2 одновременных доступов
       tasks = [access_resource(semaphore, i) for i in range(5)]
       await asyncio.gather(*tasks)
   if __name__ == "__main__":
       asyncio.run(main())
  
        asyncio.Semaphore() - это примитив синхронизации в Python's asyncio, который позволяет ограничивать количество одновременных сопрограмм (coroutines), имеющих доступ к общему ресурсу.  Это своего рода счетчик, который инициализируется с определенным значением (количество разрешенных одновременных доступов).
    
Основной принцип работы:
acquire():  Каждая сопрограмма, желающая получить доступ к ресурсу, должна вызвать метод acquire() у семафора.  Если счетчик семафора больше нуля, он уменьшается на единицу, и сопрограмма получает доступ. Если счетчик равен нулю, сопрограмма приостанавливается (переходит в состояние ожидания) до тех пор, пока другая сопрограмма не освободит семафор.release(): Когда сопрограмма заканчивает работу с ресурсом, она вызывает метод release(), который увеличивает счетчик семафора на единицу.  Если есть ожидающие сопрограммы, одна из них (в произвольном порядке, если не указано иное) возобновляет выполнение.Пример использования:
import asyncio
import random
async def worker(semaphore, worker_id):
    async with semaphore:  # Эквивалентно: await semaphore.acquire(); try: ... finally: semaphore.release()
        print(f"Worker {worker_id}: Получает доступ к ресурсу...")
        # Имитация работы с ресурсом
        await asyncio.sleep(random.uniform(0.5, 2))
        print(f"Worker {worker_id}: Завершил работу с ресурсом.")
async def main():
    # Ограничиваем количество одновременных рабочих до 3
    semaphore = asyncio.Semaphore(3)
    tasks = [worker(semaphore, i) for i in range(10)]
    await asyncio.gather(*tasks)
if __name__ == "__main__":
    asyncio.run(main())
    Разъяснение примера:
semaphore с начальным значением 3. Это означает, что только 3 сопрограммы могут одновременно находиться в критической секции (внутри контекстного менеджера async with semaphore).worker имитирует работу с общим ресурсом.  Используется async with semaphore:, что обеспечивает гарантированное освобождение семафора даже при возникновении исключений внутри блока кода.  Это эквивалентно try...finally и позволяет избежать зависаний.main создается 10 задач worker.asyncio.gather(*tasks) запускает все задачи параллельно.
        Ключевые преимущества использования asyncio.Semaphore():
        
        В заключение, asyncio.Semaphore() - это мощный инструмент для синхронизации и контроля доступа к ресурсам в асинхронном коде Python. Он позволяет создавать потокобезопасные приложения, которые эффективно используют ресурсы и избегают проблем, связанных с параллельным доступом.  Использование async with semaphore: является предпочтительным способом, так как гарантирует освобождение семафора.