Python协程:asyncio同步原语

news2024/12/26 22:34:12

在 Python 的异步编程中,asyncio 提供了一些强大的同步原语,可以帮助开发者在异步任务之间共享资源、协调状态以及避免竞争条件。本文将详细介绍其中的四种核心同步原语:LockEventConditionSemaphore


1. Lock(锁)

Lock 是最基本的同步原语,用于在多个协程之间确保共享资源的互斥访问。asyncio.Lock 的使用方式类似于线程中的 threading.Lock,但它是异步的。

使用场景
  • 确保一个协程在访问共享资源时不会被其他协程打扰。
代码示例
import asyncio

lock = asyncio.Lock()
shared_resource = 0

async def task(name):
    global shared_resource
    print(f"{name} 等待锁...")
    async with lock:  # 使用异步锁
        print(f"{name} 获得锁!")
        shared_resource += 1
        await asyncio.sleep(1)  # 模拟工作
        print(f"{name} 释放锁!")

async def main():
    await asyncio.gather(task("任务1"), task("任务2"))

asyncio.run(main())
输出示例
任务1 等待锁...
任务2 等待锁...
任务1 获得锁!
任务1 释放锁!
任务2 获得锁!
任务2 释放锁!

2. Event(事件)

Event 是一种简单的同步原语,用于在协程之间传递信号。一个协程可以等待某个事件发生,而另一个协程可以设置事件,从而唤醒所有等待的协程。

使用场景
  • 用于在协程间同步某些状态,比如触发信号或通知。
代码示例
import asyncio

event = asyncio.Event()

async def waiter():
    print("等待事件...")
    await event.wait()  # 等待事件被设置
    print("事件触发了!")

async def setter():
    print("准备触发事件...")
    await asyncio.sleep(2)
    event.set()  # 触发事件
    print("事件已触发!")

async def main():
    await asyncio.gather(waiter(), setter())

asyncio.run(main())
输出示例
等待事件...
准备触发事件...
事件已触发!
事件触发了!

3. Condition(条件变量)

Condition 是更高级的同步原语,允许协程等待某个条件满足后继续执行。它可以在某些复杂的状态控制下非常有用。

使用场景
  • 多个协程需要在特定条件下协调工作。
代码示例
import asyncio

condition = asyncio.Condition()
shared_queue = []

async def producer():
    async with condition:
        print("生产者添加项目...")
        shared_queue.append(1)  # 添加项目到共享队列
        condition.notify()  # 通知等待的消费者
        print("生产者通知消费者")

async def consumer():
    async with condition:
        while not shared_queue:
            print("消费者等待项目...")
            await condition.wait()  # 等待生产者通知
        print("消费者消费项目:", shared_queue.pop(0))

async def main():
    await asyncio.gather(consumer(), producer())

asyncio.run(main())
输出示例
消费者等待项目...
生产者添加项目...
生产者通知消费者
消费者消费项目: 1

4. Semaphore(信号量)

Semaphore 是一种计数器,限制同时运行的协程数量。asyncio.Semaphore 可以用来控制资源的最大并发访问数。

使用场景
  • 控制并发量,比如限制同时处理的网络请求数量。
代码示例
import asyncio

semaphore = asyncio.Semaphore(2)

async def task(name):
    async with semaphore:  # 每次最多允许两个任务执行
        print(f"{name} 开始执行")
        await asyncio.sleep(2)
        print(f"{name} 执行完成")

async def main():
    await asyncio.gather(task("任务1"), task("任务2"), task("任务3"), task("任务4"))

asyncio.run(main())
输出示例
任务1 开始执行
任务2 开始执行
任务1 执行完成
任务2 执行完成
任务3 开始执行
任务4 开始执行
任务3 执行完成
任务4 执行完成

总结

asyncio 的同步原语为异步任务之间的协作提供了强大的工具:

  • Lock:确保共享资源的互斥访问。
  • Event:在协程之间传递触发信号。
  • Condition:等待某个条件满足后继续执行。
  • Semaphore:限制协程的最大并发数。

通过灵活使用这些同步原语,可以有效解决异步编程中的竞争和协调问题,为复杂的异步应用提供更强的控制力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2253191.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

系统--线程互斥

1、相关背景知识 临界资源多线程、多执行流共享的资源,就叫做临界资源临界区每个线程内部,访问临界资源的代码互斥在任何时刻,保证有且只有一个执行流进入临界区,访问临界资源,对临界资源起到保护作用原子性不会被任何调度机制打断的操作,该操作只有两态,要么完成,要么…

Qt桌面应用开发 第十天(综合项目二 翻金币)

目录 1.主场景搭建 1.1重载绘制事件,绘制背景图和标题图片 1.2设置窗口标题,大小,图片 1.3退出按钮对应关闭窗口,连接信号 2.开始按钮创建 2.1封装MyPushButton类 2.2加载按钮上的图片 3.开始按钮跳跃效果 3.1按钮向上跳…

getchar()

getchar():从计算机终端(一般是键盘)输入一个字符 1、getchar返回的是字符的ASCII码值(整数)。 2、getchar在读取结束或者失败的时候,会返回EOF 输入密码并确认: scanf读取\n之前的内容即12345678 回车符…

linux 获取公网流量 tcpdump + python + C++

前言 需求为,统计linux上得上下行公网流量,常规得命令如iftop 、sar、ifstat、nload等只能获取流量得大小,不能区分公私网,所以需要通过抓取网络包并排除私网段才能拿到公网流量。下面提供了一些有效得解决思路,提供了…

Node.js:开发和生产之间的区别

Node.js 中的开发和生产没有区别,即,你无需应用任何特定设置即可使 Node.js 在生产配置中工作。但是,npm 注册表中的一些库会识别使用 NODE_ENV 变量并将其默认为 development 设置。始终在设置了 NODE_ENVproduction 的情况下运行 Node.js。…

KAN-Transfomer——基于新型神经网络KAN的时间序列预测

1.数据集介绍 ETT(电变压器温度):由两个小时级数据集(ETTh)和两个 15 分钟级数据集(ETTm)组成。它们中的每一个都包含 2016 年 7 月至 2018 年 7 月的七种石油和电力变压器的负载特征。 traffic(交通) :描…

中安证件OCR识别技术助力鸿蒙生态:智能化证件识别新体验

在数字化和智能化的浪潮中,伴随国产化战略的深入推进,国产操作系统和软件生态的建设逐渐走向成熟。鸿蒙操作系统(HarmonyOS Next)作为华为推出的重要操作系统,凭借其开放、灵活和高效的特点,正在加速在多个…

Java设计模式之状态模式架构高扩展的订单状态管理

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…

【排序用法】.NET开源 ORM 框架 SqlSugar 系列

💥 .NET开源 ORM 框架 SqlSugar 系列 🎉🎉🎉 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列…

家政小程序开发,打造便捷家政生活小程序

目前,随着社会人就老龄化和生活压力的加重,家政服务市场的需求正在不断上升,家政市场的规模也正在逐渐扩大,发展前景可观。 在市场快速发展的影响下,越来越多的企业开始进入到市场中,同时家政市场布局也发…

自然语言处理:基于BERT预训练模型的中文命名实体识别(使用PyTorch)

命名实体识别(NER) 命名实体识别(Named Entity Recognition, NER)是自然语言处理(NLP)中的一个关键任务,其目标是从文本中识别出具有特定意义的实体,并将其分类到预定义的类别中。这…

掌握 Spring Boot 中的缓存:技术和最佳实践

缓存是一种用于将经常访问的数据临时存储在更快的存储层(通常在内存中)中的技术,以便可以更快地满足未来对该数据的请求,从而提高应用程序的性能和效率。在 Spring Boot 中,缓存是一种简单而强大的方法,可以…

Unity 模拟百度地图,使用鼠标控制图片在固定区域内放大、缩小、鼠标左键拖拽移动图片

效果展示: 步骤流程: 1.使用的是UGUI,将下面的脚本拖拽到图片上即可。 using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems;public class CheckImage : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragH…

基础入门-Web应用OSS存储负载均衡CDN加速反向代理WAF防护部署影响

知识点: 1、基础入门-Web应用-防护产品-WAF保护 2、基础入门-Web应用-加速服务-CDN节点 3、基础入门-Web应用-文件托管-OSS存储 4、基础入门-Web应用-通讯服务-反向代理 5、基础入门-Web应用-运维安全-负载均衡 一、演示案例-Web-拓展架构-WAF保护-拦截攻击 原理&a…

指针(上)

目录 内存和地址 指针变量和地址 取地址(&) 解引用(*) 大小 类型 意义 const修饰 修饰变量 修饰指针 指针运算 指针- 整数 指针-指针 指针的关系运算 野指针 概念 成因 避免 assert断言 指针的使用 strl…

警惕开源信息成为泄密源头

文章目录 前言一、信息公开需谨慎1、警惕采购招标泄密。2、警惕信息公开泄密。3、警惕社交媒体泄密。 二、泄密风险需严防1、健全制度,明确责任。2、加强管控,严格审查。3、提高意识,谨言慎行。 前言 大数据时代,信息在网络空间发…

LearnOpenGL学习(光照 -- 颜色,基础光照,材质,光照贴图)

光照 glm::vec3 lightColor(0.0f, 1.0f, 0.0f); glm::vec3 toyColor(1.0f, 0.5f, 0.31f); glm::vec3 result lightColor * toyColor; // (0.0f, 0.5f, 0.0f); 说明:当我们把光源的颜色与物体的颜色值相乘,所得到的就是这个物体所反射的颜色。 创建…

面向对象(二)——类和对象(上)

1 类的定义 做了关于对象的很多介绍,终于进入代码编写阶段。 本节中重点介绍类和对象的基本定义,属性和方法的基本使用方式。 【示例】类的定义方式 // 每一个源文件必须有且只有一个public class,并且类名和文件名保持一致! …

3GPP R18 LTM(L1/L2 Triggered Mobility)是什么鬼?(三) RACH-less LTM cell switch

这篇看下RACH-less LTM cell switch。 相比于RACH-based LTM,RACH-less LTM在进行LTM cell switch之前就要先知道target cell的TA信息,进而才能进行RACH-less过程,这里一般可以通过UE自行测量或者通过RA过程获取,而这里的RA一般是通过PDCCH order过程触发。根据38.300中的描…

实验13 使用预训练resnet18实现CIFAR-10分类

1.数据预处理 首先利用函数transforms.Compose定义了一个预处理函数transform,里面定义了两种操作,一个是将图像转换为Tensor,一个是对图像进行标准化。然后利用函数torchvision.datasets.CIFAR10下载数据集,这个函数有四个常见的…