信号(Signal)、信号量(Semaphore)

news/2025/10/24 16:40:42/文章来源:https://www.cnblogs.com/xi-yongqi/p/19161852

Django的信号机制

Django 的信号机制是一套解耦工具,核心作用是:当项目中发生特定事件(如模型保存、用户登录)时,自动触发预设的操作,无需在事件发生处直接调用这些操作,从而减少代码耦合。
什么是信号
  • 通俗来说,信号就是通信双方约定的一种信息通知方式,双方通过信号来确定发生了什么事情,然后决定自己应该做什么。
  • Django有一个信号调度器(signaldispatcher),用来帮助解耦的应用获知框架内任何其他地方发生了操作。简单地说,信号允许某些发送器去通知一组接收器某些操作发生了。当许多代码段都可能对同一事件感兴趣时,信号特别有用。
核心概念
  • 理解信号机制需先明确 3 个关键组件:
  1. 信号(Signal):事件的 “通知载体”,比如 “模型保存完成”“请求结束” 等事件会对应一个信号。
  2. 发送者(Sender):触发信号的对象,通常是模型类(如User)或框架组件(如HttpRequest)。
  3. 接收器(Receiver):响应信号的函数/方法,信号被触发时,接收器会自动执行。
信号的分类
  1. 内置信号(常用场景):内置信号无需手动发送,Django 会在特定事件发生时自动触发,最常用的是模型信号和请求 / 响应信号
  2. 自定义信号
    当内置信号无法满足需求时(如自定义业务事件),可手动定义信号,完全自主控制触发时机。
信号的使用流程
  • 以 “最常用的内置信号(post_save)” 和 “自定义信号” 为例,说明完整使用步骤:
  • 场景 1:使用内置信号(以post_save为例)
    需求:用户(User模型)注册后,自动创建关联的用户资料(UserProfile模型)。
  1. 定义接收器函数
    在任意 APP 的signals.py文件中(需手动创建)编写接收器,用@receiver装饰器绑定信号:
# myapp/signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User
from myapp.models import UserProfile  # 自定义的用户资料模型# 接收器函数:User模型保存后触发
@receiver(post_save, sender=User)  # sender指定“哪个模型触发信号”
def create_user_profile(sender, instance, created, **kwargs):"""sender:触发信号的模型类(这里是User)instance:触发信号的模型实例(保存后的User对象)created:布尔值,True=新增数据,False=修改数据"""# 仅当用户是“新增”时,创建关联的UserProfileif created:UserProfile.objects.create(user=instance)  # 关联User实例
  1. 注册接收器
    需在 APP 的apps.py中注册信号,确保 Django 启动时加载接收器:
# myapp/apps.py
from django.apps import AppConfigclass MyappConfig(AppConfig):default_auto_field = 'django.db.models.BigAutoField'name = 'myapp'# 启动时加载信号接收器def ready(self):import myapp.signals  # 导入signals.py文件
  1. 测试效果
    当执行User.objects.create(username="test", password="123")时,post_save信号会自动触发,create_user_profile接收器执行,自动创建对应的UserProfile实例。
  • 场景 2:自定义信号
    需求:当用户完成订单支付后,触发 “发送支付成功通知”“更新库存” 两个操作,用自定义信号解耦。
  1. 定义信号
    在signals.py中用Signal类定义自定义信号:
# myapp/signals.py
from django.dispatch import Signal# 自定义信号:订单支付成功信号(可指定需要传递的参数)
order_paid_signal = Signal(providing_args=["order", "amount"])  # providing_args指定信号携带的参数
  1. 定义接收器
    为自定义信号绑定多个接收器(支持一个信号触发多个操作):
# myapp/signals.py(接上面代码)
from django.dispatch import receiver
from myapp.models import Order, Product# 接收器1:发送支付成功通知
@receiver(order_paid_signal)
def send_payment_notification(sender, order, amount, **kwargs):print(f"订单{order.id}支付成功,金额{amount}元,已发送通知")# 接收器2:更新商品库存
@receiver(order_paid_signal)
def update_product_stock(sender, order, amount, **kwargs):# 假设订单关联了商品,这里减少对应商品的库存for item in order.orderitem_set.all():product = item.productproduct.stock -= item.quantityproduct.save()print(f"订单{order.id}对应的商品库存已更新")
  1. 手动触发信号
    在 “支付成功” 的业务逻辑中,手动发送信号(自定义信号不会自动触发,需显式调用):
# myapp/views.py
from django.shortcuts import get_object_or_404
from myapp.models import Order
from myapp.signals import order_paid_signaldef payment_success(request, order_id):order = get_object_or_404(Order, id=order_id)amount = order.total_amount# 关键:手动发送自定义信号,传递参数order_paid_signal.send(sender=Order,  # 发送者(通常是关联模型类)order=order,   # 信号携带的订单实例amount=amount  # 信号携带的金额参数)return HttpResponse("支付成功")
  1. 测试效果
    当访问payment_success视图(订单支付成功后),order_paid_signal会被触发,两个接收器自动执行,分别发送通知和更新库存。

总结

Django 信号机制的核心价值是解耦—— 让 “事件发生” 和 “事件后续操作” 分离,比如用户注册(事件)与创建资料、发送通知(后续操作)无需写在同一处代码,便于维护和扩展。
  • 适用场景:
  1. 跨 APP 的操作联动(如 A 模型变更后,BAPP 的模型需同步更新);
  2. 框架级事件的响应(如监听请求、用户登录);
  3. 业务逻辑的拆分(如支付成功后触发多个独立操作)。
  • 不适用场景:
  1. 有严格执行顺序的操作(信号接收器顺序不可控);
  2. 高并发、高性能要求的场景(同步信号会阻塞)。

信号量

  • 并发编程中概念
    在Python中,信号量(Semaphore)主要用来控制多个线程或进程对共享资源的访问。信号量本质上是一种计数器的锁,它维护一个许可(permit)数量,每次 acquire() 函数被调用时,如果还有剩余的许可,则减少一个,并允许执行;如果没有剩余许可,则阻塞当前线程直到其他线程释放信号量
信号量本质是一个计数器 + 等待队列,通过两个核心操作(P 操作、V 操作)控制资源访问:
  1. 计数器:记录当前可用的 “共享资源名额”(比如允许 3 个线程同时访问数据库,计数器初始值就是 3)。
  2. P 操作(获取资源):线程要访问共享资源时,先执行 P 操作 —— 计数器减 1;若计数器 < 0,线程进入等待队列,直到有其他线程释放资源。
  3. V 操作(释放资源):线程用完资源后,执行 V 操作 —— 计数器加 1;若计数器≤0,唤醒等待队列中的一个线程,让它获取资源。
    简单说:信号量就像 “资源管理员”,限制同时使用资源的 “人数”,避免拥挤。
  • 在 Django 项目中,信号量主要用于处理并发场景,比如:
  1. 限制异步任务并发数:用 Celery 处理异步任务时,用信号量限制同时执行的任务数(避免服务器过载);
  2. 控制数据库并发连接:如上述示例,避免多线程同时访问数据库导致连接池耗尽;
  3. 共享资源保护:如多线程同时读写本地文件、调用第三方 API(限制 API 调用频率)。
  • Python 的threading(线程)和multiprocessing(进程)模块都内置了信号量实现,以下是最常用的线程信号量示例(Django 中处理并发请求时可能用到)。
    示例场景:限制同时访问数据库的线程数
    假设 Django 项目中,多个线程需要查询数据库,但数据库最多支持 2 个并发连接,用信号量控制:
import threading
import time
# 模拟Django中的数据库查询函数
def mock_db_query(thread_name, semaphore):# 1. P操作:获取资源(尝试占用1个数据库连接名额)semaphore.acquire()try:print(f"[{thread_name}] 开始查询数据库(当前可用名额:{semaphore._value})")time.sleep(2)  # 模拟数据库查询耗时print(f"[{thread_name}] 数据库查询完成")finally:# 2. V操作:释放资源(归还数据库连接名额)semaphore.release()print(f"[{thread_name}] 释放数据库连接(当前可用名额:{semaphore._value})")# 3. 创建信号量:初始值=2(允许2个线程同时访问数据库)
db_semaphore = threading.Semaphore(value=2)# 4. 创建5个线程(模拟5个并发请求需要查询数据库)
threads = []
for i in range(5):thread = threading.Thread(target=mock_db_query,args=(f"线程{i+1}", db_semaphore))threads.append(thread)thread.start()# 等待所有线程执行完成
for thread in threads:thread.join()

结果:

[线程1] 开始查询数据库(当前可用名额:1)
[线程2] 开始查询数据库(当前可用名额:0)
[线程1] 数据库查询完成
[线程1] 释放数据库连接(当前可用名额:1)
[线程3] 开始查询数据库(当前可用名额:0)
[线程2] 数据库查询完成
[线程2] 释放数据库连接(当前可用名额:1)
[线程4] 开始查询数据库(当前可用名额:0)
[线程3] 数据库查询完成
[线程3] 释放数据库连接(当前可用名额:1)
[线程5] 开始查询数据库(当前可用名额:0)
[线程4] 数据库查询完成
[线程4] 释放数据库连接(当前可用名额:1)
[线程5] 数据库查询完成
[线程5] 释放数据库连接(当前可用名额:2)'''
前 2 个线程能直接获取资源(名额从 2→0);
第 3-5 个线程会等待,直到有线程释放名额(名额≥1)才会执行;
始终只有≤2 个线程同时访问数据库,避免资源竞争。
'''

关键注意事项

  • 避免死锁:线程执行 P 操作后,必须确保执行 V 操作(即使发生异常),否则计数器会一直减少,最终所有线程都无法获取资源(死锁)。建议用try...finally包裹资源操作,在finally中执行 V 操作。
  • 区分线程 / 进程信号量:
    threading.Semaphore:用于同一进程内的线程同步;
    multiprocessing.Semaphore:用于不同进程间的同步(需结合进程间通信机制);
    两者不能混用,否则无法实现同步效果。
    不要过度使用:信号量主要解决 “资源竞争”,若没有共享资源(如线程各自处理独立数据),无需使用信号量,否则会增加代码复杂度。

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

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

相关文章

在 macOS 中遇到 brew 命令不存在的问题

在 macOS 中遇到 brew 命令不存在的问题Posted on 2025-10-24 16:38 挥辉 阅读(0) 评论(0) 收藏 举报在 macOS 中遇到 brew 命令不存在的问题,通常是因为 Homebrew 未安装或未正确配置环境变量。以下是解决方法:…

在线聊天室

在线聊天室,输入用户名,房间名和密码,就可以进入同一个聊天室。(聊天室唯一性由房间名和密码的hash保证) https://peersuite.space/

2025 年亚克力大型鱼缸厂家联系方式推荐:江苏金穗的全产业链服务与定制化技术优势解析

行业背景 当下,商业展览、高端酒店、私人别墅等领域对亚克力大型鱼缸的需求日益增长,这类鱼缸因通透美观、空间适配性强等特点,成为提升环境档次的重要元素。但行业发展面临不少挑战:部分厂家缺乏厚板加工能力,无…

2025 年海洋水族馆厂家联系方式推荐:江苏金穗亚克力定制服务与工程案例,泳池 / 鱼缸项目解决方案

行业背景 当前海洋水族馆行业蓬勃发展,随着文旅产业升级与消费需求多元化,市场对高品质亚克力配套产品的需求持续攀升。据行业数据显示,国内海洋馆、水族馆建设项目年均增长 15% 以上,同时家庭高端鱼缸、商业无边泳…

例3.3】三个数 ------信息奥赛高级题库

按从小到大的顺序排 方法就是if嵌套和swap函数

详细介绍:Go 和云原生 的现状和发展前景

详细介绍:Go 和云原生 的现状和发展前景2025-10-24 16:36 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block…

Socket 编程 TCP(准备阶段) - 指南

Socket 编程 TCP(准备阶段) - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco&…

2025 年亚克力板材厂家联系方式推荐:江苏金穗技术工艺与工程案例解析,泳池 / 鱼缸 / 海洋馆解决方案

行业背景 2025 年全球亚克力板市场规模将达 45 亿美元,中国市场规模预计突破 300 亿元,华东地区产量占比超 40%。随着高端化与定制化需求提升,市场对亚克力板材的透光性、厚板加工及异形定制能力提出更高要求。但行…

2025 年 亚克力透明泳池厂家联系方式推荐:江苏金穗的技术积淀与工程服务优势解析

行业背景 随着文旅地产、高端民宿及别墅市场的蓬勃发展,亚克力透明泳池因兼具视觉观赏性与空间艺术性,需求持续攀升。但行业现存诸多痛点:部分厂家透光率不足影响观景效果,厚板加工与无缝拼接技术欠缺导致漏水隐患…

2025山东单招综评培训机构推荐榜:济南易升教育五星领跑,小班培养 + 高上岸率适配升学需求

随着单招综评成为升学重要路径,2025 年山东地区一批专注该领域的教育机构凭借硬实力脱颖而出。以下推荐榜基于真实办学成果与服务能力筛选,为考生提供客观参考。 济南易升教育学校(易升权合教育) 🌟🌟🌟🌟…

实用指南:npm 包构建与发布

实用指南:npm 包构建与发布pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco",…

2025修护/二硫化硒去屑/香氛/控油蓬松/洗发水品牌推荐榜:MASIL 玛丝兰(西安悦己容)五星领衔,这些专研洗护品牌值得关注

在洗护市场愈发注重 “专业养护” 的 2025 年,兼具技术实力与用户口碑的洗发水品牌成为主流选择。以下推荐榜基于企业真实实力与产品定位筛选,为消费者提供客观参考。 西安悦己容生物科技有限责任公司(MASIL 玛丝兰…

2025年Q345B/20G/5310/无缝钢管 高压/5310高压/6479高压合金管推荐榜:天津大无缝五星领跑,这些品质流通企业适配工业需求

2025 年工业制造、能源输送等领域对无缝钢管、合金管的品质稳定性与供应效率要求持续提升,一批兼具资源整合能力与服务意识的企业凸显,以下推荐榜基于真实经营实力筛选,供采购参考。 天津大无缝联合钢铁有限公司 �…

2025年保险法律服务律所推荐:拒赔点外险保险律师聚焦专业与实战能力的权威之选

随着保险产品日益多元,理赔纠纷、条款争议等问题频发,选择专业的保险法律服务机构成为化解矛盾的关键。基于案件胜诉率、领域专注度、服务覆盖范围等核心维度,结合行业实践与客户反馈,现梳理出值得关注的保险律师事…

vue3+vite学习日记之配置全新项目

一、先创建项目并进行一些安装配置 1、npm create vite@latest ->输入项目名称->选择vue->选择ts->根据提示进行 2、安装vue-router,输入命令npm install vue-router@4 -s 3、安装element-plus,输入命令…

2025 全案/VI/品牌设计公司服务商推荐:意识形体(上海意感)五星领跑,这些专注视觉价值的公司值得选

在商业竞争愈发依赖 “视觉话语权” 的当下,品牌设计成为传递品牌内核、激活用户连接的关键。2025 年,一批以专业设计能力驱动品牌成长的服务商凸显,以下推荐榜聚焦真实实力,为品牌方提供参考。 上海意感品牌形象策…

2025 年水泥房厂家联系方式推荐,内蒙古蒙营新型建材提供预制水泥房及配套产品专业解决方案

行业背景 随着我国城镇化进程的推进和建筑行业工业化转型加速,预制水泥制品凭借施工效率高、质量稳定、节能环保等优势,在市政建设与民用建筑领域的应用愈发广泛。其中,预制水泥房因具备组装便捷、空间利用率高、使…

一网统管,智慧赋能:国标GB28181算法算力平台EasyGBS构建城市交通可视、巡检与指挥新范式

一网统管,智慧赋能:国标GB28181算法算力平台EasyGBS构建城市交通可视、巡检与指挥新范式一、方案背景 人车暴涨,路口告急:高峰堵、事故慢、取证难,老办法已拖不动城市交通。破局之道,先看摄像头——国标GB28181算…

YouTube数据抓取漏洞利用与概念验证解析

本文详细解析了YouTube数据抓取概念验证项目的技术实现,包括Python代码编写、GitHub CoPilot辅助开发、YouTube API数据采集以及CSV文件生成等关键技术细节,展示了完整的数据抓取技术架构。https://sploitus.com/exp…

2025 年检查井厂家联系方式推荐,内蒙古蒙营新型建材提供专业检查井解决方案与可靠产品供应

在当前市政建设与民用建筑快速发展的背景下,检查井作为排水、电力、通信等系统的关键配套设施,其质量与供应稳定性直接影响工程整体质量和使用寿命。随着行业对检查井的规格标准化、性能可靠化要求不断提升,市场对专…