太原做网站 小程序可视化在线做网站

张小明 2026/1/2 10:31:28
太原做网站 小程序,可视化在线做网站,网站如何提交百度收录,公司建设网站的公司经常使用freertos进行开发的用户都会经常使用互斥锁的功能#xff0c;主要是用于实现原子操作#xff0c;避免冲突#xff0c;但是在合宙的luatos上#xff0c;其实没有相关的api接口#xff0c;lua本身也不支持这样操作#xff0c;于是本人研究了一下#xff0c;写出了…经常使用freertos进行开发的用户都会经常使用互斥锁的功能主要是用于实现原子操作避免冲突但是在合宙的luatos上其实没有相关的api接口lua本身也不支持这样操作于是本人研究了一下写出了一个库用于实现互斥锁的功能可能不太完善欢迎交流实现原理有人会说lua本身就是协程式的多仍任务要锁做什么是这样的确实也不需要但是复杂任务的时候比如串口抢占websocket抢占都涉及到先后操作和逻辑竞争这个时候就需要锁了而要实现互斥锁我们需要两个核心的apisys.waitUntil和sys.publishsys.waitUntil(msg, timeout)对应 RTOS 的Block (阻塞等待)。它会让当前协程挂起直到收到指定的消息或超时。sys.publish(msg)对应 RTOS 的Unblock (唤醒)。它会广播一个消息唤醒所有正在等待该消息的协程。我们可以在此基础上封装成类实现互斥锁实现代码-- lib_mutex.lualocalMutex{}Mutex.__indexMutex-- 创建一个新的互斥锁functionMutex.new()localo{lockedfalse,-- 锁状态ownernil,-- 持有者idtostring(os.time())..tostring(math.random())-- 生成唯一等待ID}returnsetmetatable(o,Mutex)end-- 获取锁 (类似 xSemaphoreTake)-- timeout: 超时时间(ms)默认为一直等待-- 返回值: true 成功获取, false 超时失败functionMutex:lock(timeout)localwait_result-- 如果锁已经被占用了就挂起当前协程等待iftimeoutandtype(timeout)numberthentimeoutmath.floor(timeout)endwhileself.lockeddo-- 当前协程会停在这里直到有人调用 unlock 触发消息或者超时wait_resultsys.waitUntil(self.id,timeout)-- 如果是因为超时醒来的 (wait_result 为 nil)则抢锁失败ifwait_resultnilthenreturnfalseend-- 如果是被唤醒的循环会继续再次检查 self.lockedend-- 成功抢到锁self.lockedtrueself.ownercoroutine.running()-- 记录是谁拿了锁returntrueend-- 释放锁 (类似 xSemaphoreGive)functionMutex:unlock()-- 只有锁的持有者才能释放锁 (防止误操作可选)ifself.owner~coroutine.running()thenreturnendifself.lockedthenself.lockedfalseself.ownernil-- 醒来后会重新进入 while 循环抢锁由于 Lua 是单线程必定有一个会先抢到其他的继续睡sys.publish(self.id)endendreturnMutex代码解释很罗嗦可跳过首先看数据结构的设计在 Mutex.new 构造函数中我们定义了锁的三个元数据locked 状态位用于原子性地标记资源是否被占用owner 用于记录持有当前锁的协程句柄这至关重要它确保了“谁加锁谁解锁”的安全原则防止其他任务意外释放不属于自己的锁而 id 则是一个由时间戳和随机数生成的唯一字符串它作为消息通道的唯一标识符保证了系统内不同锁对象之间的事件广播互不干扰。接下来是至关重要的上锁逻辑 Mutex:lock。该函数首先对传入的超时参数进行了整数化处理math.floor这是为了防止浮点数导致底层定时器崩溃。紧接着进入核心的竞争循环这里使用 while self.locked 循环而不是简单的 if 判断是因为在多任务环境下当锁被释放并广播消息时可能有多个等待中的协程同时被唤醒但由于 Lua 是单线程执行的它们只能依次运行。假设任务 A 和 B 同时被唤醒A 先运行发现锁空闲并抢占了它当 B 随后运行时必须能再次检测到锁已被 A 抢占locked 变回 true从而再次进入 sys.waitUntil 挂起等待。当 waitUntil 返回代表超时的结果时直接返回 false避免任务无限期死等。一旦成功跳出循环函数立即标记 locked 为 true 并记录当前协程为 owner由于 Lua 协程的非抢占特性这两步操作中间不会被打断从而保证了加锁过程的原子性。最后是解锁逻辑 Mutex:unlock。为了保证业务逻辑的安全性代码首先通过 coroutine.running() 校验当前协程是否为锁的持有者有点类似递归锁或二值信号量的所有权保护防止非持有者误操作破坏业务逻辑。校验通过后将 locked 状态重置为 false 并清空 owner随即调用 sys.publish(self.id) 广播消息。这一步是整个机制的触发器它通知 LuatOS 调度器查找所有正在该 id 上阻塞等待的协程将它们的状态从“挂起”转为“就绪”使它们在下一个调度周期有机会重新进入 lock 函数的循环中竞争资源。测试代码localMutexrequiremutex-- 创建一个全局锁保护“扬声器”资源localspeaker_lockMutex.new()-- 模拟 TTS 播放函数localfunctionspeak(text)log.info(TTS,准备播放:,text)-- 尝试拿锁等待时间无限ifspeaker_lock:lock()thenlog.info(LOCK,text,拿到锁了开始播放...)-- 模拟播放过程耗时 2秒sys.wait(2000)log.info(TTS,播放结束:,text)-- 释放锁speaker_lock:unlock()log.info(LOCK,锁已释放)elselog.info(LOCK,获取锁超时/失败)endendlog.info(TTS,拿锁比赛现在开始)-- 任务 A每 3 秒想说话sys.taskInit(function()whiletruedospeak(我是任务 A)sys.wait(3000)endend)-- 任务 B每 1 秒想说话sys.taskInit(function()sys.wait(500)whiletruedospeak(我是任务 B)sys.wait(1000)endend)sys.run()下面式运行日志[2025-12-17 17:57:32.702][000000000.232] D/main loadlibs psram 3211632 104972 106200 [2025-12-17 17:57:32.705][000000000.251] I/user.main Air780EGH_gnss 1.0.0 [2025-12-17 17:57:32.708][000000000.252] I/user.main Air780EGH_gnss [2025-12-17 17:57:32.711][000000000.480] I/user.TTS 拿锁比赛现在开始 [2025-12-17 17:57:32.713][000000000.481] I/user.TTS 准备播放: 我是任务 A [2025-12-17 17:57:32.716][000000000.481] I/user.LOCK 我是任务 A 拿到锁了开始播放... [2025-12-17 17:57:32.898][000000000.992] I/user.TTS 准备播放: 我是任务 B [2025-12-17 17:57:33.944][000000002.006] D/mobile cid1, state0 [2025-12-17 17:57:33.950][000000002.006] D/mobile bearer act 0, result 0 [2025-12-17 17:57:33.953][000000002.007] D/mobile NETIF_LINK_ON - IP_READY [2025-12-17 17:57:33.970][000000002.063] D/mobile TIME_SYNC 0 [2025-12-17 17:57:34.266][000000002.358] soc_cms_proc 2219:cenc report 1,51,1,15 [2025-12-17 17:57:34.376][000000002.463] D/mobile NETIF_LINK_ON - IP_READY [2025-12-17 17:57:34.390][000000002.481] I/user.TTS 播放结束: 我是任务 A [2025-12-17 17:57:34.393][000000002.482] I/user.LOCK 锁已释放 [2025-12-17 17:57:34.395][000000002.483] I/user.LOCK 我是任务 B 拿到锁了开始播放... [2025-12-17 17:57:35.526][000000003.628] D/mobile ims reg state 0 [2025-12-17 17:57:35.529][000000003.629] D/mobile LUAT_MOBILE_EVENT_CC status 0 [2025-12-17 17:57:35.531][000000003.629] D/mobile LUAT_MOBILE_CC_READY [2025-12-17 17:57:36.383][000000004.483] I/user.TTS 播放结束: 我是任务 B [2025-12-17 17:57:36.385][000000004.484] I/user.LOCK 锁已释放 [2025-12-17 17:57:37.394][000000005.482] I/user.TTS 准备播放: 我是任务 A [2025-12-17 17:57:37.397][000000005.483] I/user.LOCK 我是任务 A 拿到锁了开始播放... [2025-12-17 17:57:37.398][000000005.484] I/user.TTS 准备播放: 我是任务 B [2025-12-17 17:57:39.385][000000007.483] I/user.TTS 播放结束: 我是任务 A [2025-12-17 17:57:39.388][000000007.484] I/user.LOCK 锁已释放 [2025-12-17 17:57:39.391][000000007.485] I/user.LOCK 我是任务 B 拿到锁了开始播放... [2025-12-17 17:57:41.390][000000009.485] I/user.TTS 播放结束: 我是任务 B [2025-12-17 17:57:41.394][000000009.486] I/user.LOCK 锁已释放 [2025-12-17 17:57:42.389][000000010.484] I/user.TTS 准备播放: 我是任务 A [2025-12-17 17:57:42.393][000000010.485] I/user.LOCK 我是任务 A 拿到锁了开始播放... [2025-12-17 17:57:42.395][000000010.486] I/user.TTS 准备播放: 我是任务 B [2025-12-17 17:57:44.384][000000012.485] I/user.TTS 播放结束: 我是任务 A [2025-12-17 17:57:44.387][000000012.486] I/user.LOCK 锁已释放 [2025-12-17 17:57:44.390][000000012.487] I/user.LOCK 我是任务 B 拿到锁了开始播放... [2025-12-17 17:57:46.387][000000014.487] I/user.TTS 播放结束: 我是任务 B [2025-12-17 17:57:46.390][000000014.488] I/user.LOCK 锁已释放 [2025-12-17 17:57:47.384][000000015.486] I/user.TTS 准备播放: 我是任务 A [2025-12-17 17:57:47.387][000000015.487] I/user.LOCK 我是任务 A 拿到锁了开始播放... [2025-12-17 17:57:47.389][000000015.488] I/user.TTS 准备播放: 我是任务 B [2025-12-17 17:57:49.400][000000017.487] I/user.TTS 播放结束: 我是任务 A [2025-12-17 17:57:49.403][000000017.488] I/user.LOCK 锁已释放 [2025-12-17 17:57:49.404][000000017.489] I/user.LOCK 我是任务 B 拿到锁了开始播放... [2025-12-17 17:57:51.402][000000019.489] I/user.TTS 播放结束: 我是任务 B [2025-12-17 17:57:51.405][000000019.490] I/user.LOCK 锁已释放 [2025-12-17 17:57:52.399][000000020.488] I/user.TTS 准备播放: 我是任务 A [2025-12-17 17:57:52.405][000000020.489] I/user.LOCK 我是任务 A 拿到锁了开始播放... [2025-12-17 17:57:52.407][000000020.490] I/user.TTS 准备播放: 我是任务 B [2025-12-17 17:57:54.390][000000022.489] I/user.TTS 播放结束: 我是任务 A [2025-12-17 17:57:54.393][000000022.490] I/user.LOCK 锁已释放 [2025-12-17 17:57:54.396][000000022.491] I/user.LOCK 我是任务 B 拿到锁了开始播放... [2025-12-17 17:57:56.390][000000024.491] I/user.TTS 播放结束: 我是任务 B [2025-12-17 17:57:56.394][000000024.492] I/user.LOCK 锁已释放分析每个任务持有的时长可以看到锁是成功起效了并没有出现ab同时抢任务的问题以上就是我的设计虽然大家一般用lua都不会开发很复杂的程序但是凡是都有个例外此外还有人可能会说那我用table实现队列不也能执行你这个操作吗你这个操作的好处是什么用锁的话主要是更线性更符合直觉队列需要关注时序的问题还需要一个队列常驻后台实现轮询/等待唤起这样。
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

江西省住房建设部官方网站建立品牌网站的

15亿参数重塑多模态AI格局:字节跳动Tar-1.5B开源背后的技术革命与产业机遇 【免费下载链接】Tar-1.5B 项目地址: https://ai.gitcode.com/hf_mirrors/ByteDance-Seed/Tar-1.5B 导语 字节跳动Seed团队正式开源Tar-1.5B多模态大模型,通过突破性的…

张小明 2026/1/1 2:37:41 网站建设

聊城网站备案谷歌网站网址

UNIX 系统中 vi 编辑器的多场景应用与技巧 在 UNIX 系统里,vi 编辑器是一款功能强大且应用广泛的工具。随着时间的推移,vi 的命令结构已被应用到众多应用程序中。若不熟悉 vi 的操作,在使用某些应用时可能会遇到困难。下面将介绍 vi 在不同场景下的应用。 1. UNIX 邮件中的…

张小明 2026/1/1 8:19:54 网站建设

通道县城市建设投资有限公司网站wordpress 页面插件

Llama-Factory 能否支持联邦学习?隐私保护下的大模型微调新路径 在医疗、金融和政务等对数据隐私高度敏感的领域,企业越来越希望利用大语言模型(LLM)提升业务智能化水平。然而,一个现实困境摆在面前:要让模…

张小明 2025/12/31 10:56:01 网站建设

女网友叫我一起做优惠券网站福州优化搜索引擎

Ncorr数字图像相关软件新手实战指南:从零基础到精通 【免费下载链接】ncorr_2D_matlab 2D Digital Image Correlation Matlab Software 项目地址: https://gitcode.com/gh_mirrors/nc/ncorr_2D_matlab 还在为材料变形分析发愁吗?🤔 今…

张小明 2025/12/31 10:25:17 网站建设

建设企业网站个人网站建设与实现毕业设计

运维怎么转行网络安全?(非常详细)从零基础入门到精通,收藏这一篇就够了 经常有人问我:干网工、干运维多年遇瓶颈,想学点新技术给自己涨涨“身价”,应该怎么选择? 聪明人早已经用脚…

张小明 2026/1/1 6:33:45 网站建设

淮南建设网站网站收录原创文章

ARCore Unity SDK完整开发指南:从零基础到实战应用 【免费下载链接】arcore-unity-sdk ARCore SDK for Unity 项目地址: https://gitcode.com/gh_mirrors/ar/arcore-unity-sdk 快速入门:搭建你的第一个AR场景 ARCore Unity SDK是谷歌官方推出的增…

张小明 2026/1/1 12:20:35 网站建设