Go Goroutine数据定时输出:共享状态与互斥锁实践

Go Goroutine数据定时输出:共享状态与互斥锁实践

本文将详细介绍如何在go语言中,从一个长时间运行的goroutine中周期性地获取并展示其内部数据。核心方法是利用一个由sync.rwmutex保护的共享状态变量,确保多goroutine访问时的线程安全。同时,结合time.tick定时器机制,在主goroutine中以固定频率轮询并打印这些更新的数据,从而提供一种无需完全依赖channel即可实现goroutine间状态报告的有效模式。

在Go语言的并发编程中,goroutine是轻量级的执行单元。当一个goroutine执行长时间任务时,我们常常需要周期性地获取其当前状态或最新数据,并在主程序或其他goroutine中进行展示。虽然Go的channel是实现goroutine间通信的强大工具,但对于这种“定时查询当前状态”的需求,直接使用共享内存配合互斥锁可能是一种更简洁高效的解决方案。本文将探讨如何利用sync.RWMutex保护共享状态,并通过定时器机制实现goroutine数据的周期性输出。

核心概念:共享状态与读写互斥锁

当多个goroutine需要访问和修改同一块内存区域时,如果不加以保护,就可能导致数据竞态(data race),从而产生不可预测的结果。Go语言提供了sync包中的并发原语来解决这个问题,其中sync.RWMutex(读写互斥锁)是处理读多写少场景的理想选择。

sync.RWMutex的特性:

写锁(Lock/Unlock): 只有一个goroutine可以持有写锁。当写锁被持有,所有读锁和写锁的请求都会被阻塞。读锁(RLock/RUnlock): 多个goroutine可以同时持有读锁。当没有写锁被持有,读锁不会相互阻塞。但如果存在写锁,或有写锁请求正在等待,新的读锁请求可能会被阻塞。

在这种定时报告场景中,长时间运行的goroutine会不断“写入”最新的进度数据,而主goroutine会周期性地“读取”这些数据。sync.RWMutex能够很好地平衡读写操作,提高并发性能。

实现步骤与示例

我们将通过一个具体的Go程序来演示如何实现这一机制。程序包含一个模拟长时间运行任务的longJob goroutine,以及一个负责定时打印其进度的main goroutine。

定义共享状态结构体:创建一个结构体来封装需要共享的数据和sync.RWMutex。

type Progress struct {    current string      // 存储当前进度信息    rwlock  sync.RWMutex // 读写互斥锁}

实现线程安全的数据更新与读取方法:为Progress结构体添加Set和Get方法,分别用于更新和获取进度,并确保在操作时正确加锁和解锁。

// Set 方法用于更新进度,使用写锁保护func (p *Progress) Set(value string) {    p.rwlock.Lock()   // 获取写锁    defer p.rwlock.Unlock() // 确保在函数退出时释放写锁    p.current = value}// Get 方法用于获取进度,使用读锁保护func (p *Progress) Get() string {    p.rwlock.RLock()  // 获取读锁    defer p.rwlock.RUnlock() // 确保在函数退出时释放读锁    return p.current}

长时间运行的Goroutine:longJob函数模拟一个持续进行的工作,它会周期性地更新Progress对象中的数据。

func longJob(progress *Progress) {    i := 0    for {        time.Sleep(100 * time.Millisecond) // 模拟工作耗时        i++        progress.Set(fmt.Sprintf("Current progress message: %v", i)) // 更新进度    }}

主Goroutine与定时器:main函数负责启动longJob goroutine,并使用time.Tick创建一个定时器,每隔一秒读取并打印一次进度。

func main() {    fmt.Println("程序开始运行...")    // 初始化Progress对象    progress := &Progress{}    // 启动longJob goroutine    go longJob(progress)    // 创建一个定时器,每秒触发一次    c := time.Tick(1 * time.Second)    // 循环监听定时器事件    for {        select {        case <-c: // 当定时器触发时            fmt.Println("当前进度:", progress.Get()) // 获取并打印最新进度        }    }}

完整示例代码

package mainimport (    "fmt"    "sync"    "time")// Progress 结构体用于存储共享进度信息,并包含一个读写互斥锁type Progress struct {    current string    rwlock  sync.RWMutex}// Set 方法用于更新进度,使用写锁保护,确保写入操作的原子性func (p *Progress) Set(value string) {    p.rwlock.Lock()    defer p.rwlock.Unlock()    p.current = value}// Get 方法用于获取进度,使用读锁保护,允许多个goroutine同时读取func (p *Progress) Get() string {    p.rwlock.RLock()    defer p.rwlock.RUnlock()    return p.current}// longJob 模拟一个长时间运行的任务,它会持续更新Progress对象func longJob(progress *Progress) {    i := 0    for {        time.Sleep(100 * time.Millisecond) // 模拟每次工作耗时100毫秒        i++        // 更新共享的进度信息        progress.Set(fmt.Sprintf("Current progress message: %v", i))    }}func main() {    fmt.Println("程序开始运行...")    // 初始化Progress对象,用于存储和保护进度数据    progress := &Progress{}    // 启动longJob goroutine,使其在后台运行并更新进度    go longJob(progress)    // 创建一个定时器,每隔1秒发送一个信号到通道c    // time.Tick 返回一个 channel,每隔指定时间间隔发送一个时间值    c := time.Tick(1 * time.Second)    // 主goroutine进入无限循环,等待定时器信号    for {        select {        case <-c: // 当从定时器通道c接收到信号时            // 获取并打印当前进度            fmt.Println("当前进度:", progress.Get())        }    }}

注意事项与最佳实践

sync.RWMutex 的选择:

如果读操作远多于写操作,sync.RWMutex 是一个很好的选择,因为它允许多个并发读。如果读写频率相近,或者写操作非常频繁,sync.Mutex 可能会更简单且性能差异不大。对于简单的计数器等原子操作,sync/atomic 包提供了更高效的原子操作。

time.Tick 与 time.NewTicker:

time.Tick 是一个便捷函数,它返回一个只读的通道,不需要手动停止。然而,它会一直运行,直到程序结束,如果不再需要,可能会导致资源泄漏。time.NewTicker 返回一个*time.Ticker对象,它有一个Stop()方法。在长时间运行的程序中,如果定时器生命周期有限,推荐使用time.NewTicker并在不再需要时调用Stop()来释放资源。在本示例中,由于程序是无限循环,time.Tick是可接受的。

数据竞态的避免:始终确保对共享变量的访问通过互斥锁进行保护。忘记加锁是并发编程中最常见的错误之一。

死锁防范:避免在持有锁的情况下尝试获取另一个锁,或者以不一致的顺序获取多个锁,这可能导致死锁。本示例中只涉及一个锁,风险较低。

替代方案:Channel虽然本文采用共享状态和互斥锁,但

以上就是Go Goroutine数据定时输出:共享状态与互斥锁实践的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1421825.html

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
Go语言:优化文件日期提取函数的惯用实践
上一篇 2025年12月16日 16:19:35
Golang如何开发基础的定时任务_Golang定时任务项目实战
下一篇 2025年12月16日 16:19:45

相关推荐

  • Android应用开发:使用Intent实现页面跳转

    Android应用开发:使用Intent实现页面跳转Android应用开发:使用Intent实现页面跳转Android应用开发:使用Intent实现页面跳转Android应用开发:使用Intent实现页面跳转

    本文将介绍如何在Android应用中实现页面之间的跳转。通过使用Intent,我们可以轻松地从一个Activity切换到另一个Activity。本文将提供示例代码和详细步骤,帮助你理解Intent的基本用法,并掌握在按钮点击事件中启动新Activity的方法。 在Android应用开发中,页面跳转是…

    2026年9月28日 • 用户投稿
    000
  • 格子达论文查重怎么操作_格子达官方检测系统指南

    格子达论文查重怎么操作_格子达官方检测系统指南格子达论文查重怎么操作_格子达官方检测系统指南格子达论文查重怎么操作_格子达官方检测系统指南格子达论文查重怎么操作_格子达官方检测系统指南

    首先登录格子达官网注册账号并登录,接着在个人中心上传符合格式的论文文件,填写必要信息后提交检测,最后等待系统生成报告并下载查看总相似比、AI占比等数据,结合标注内容进行修改。 格子达论文查重怎么操作?这是不少网友都关注的,接下来由PHP小编为大家带来格子达官方检测系统指南,感兴趣的网友一起随小编来瞧…

    2026年9月28日 • 用户投稿
    000
  • Android 应用中页面(Activity)间导航的实现指南

    Android 应用中页面(Activity)间导航的实现指南Android 应用中页面(Activity)间导航的实现指南Android 应用中页面(Activity)间导航的实现指南Android 应用中页面(Activity)间导航的实现指南

    本文详细介绍了在 Android 应用中如何通过按钮实现不同页面(Activity)之间的切换。核心机制是使用 Intent 对象来指定目标 Activity,并通过 startActivity() 方法启动它。文章提供了 MainActivity.java 中的示例代码,并强调了 AndroidM…

    2026年9月28日 • 用户投稿
    000
  • 运维新概念:高效积累之道

    运维新概念:高效积累之道运维新概念:高效积累之道运维新概念:高效积累之道运维新概念:高效积累之道

    当前技术更新日新月异,各类语言、工具和理念层出不穷,令人应接不暇。唯有持续学习、不断吸收新知,方能紧跟发展潮流,不被时代淘汰。 1、 IT部门面临诸多挑战 2、 目前,IT部门整体尚未获得充分认可。尽管信息化在各单位日益重要,仍有部分管理者将其视为单纯的成本支出部门,认为其只消耗资源而无法直接创收,…

    2026年9月28日 • 用户投稿
    100
  • 如何下载豆包AI应用 豆包AI应用下载与安装步骤解析

    如何下载豆包AI应用 豆包AI应用下载与安装步骤解析如何下载豆包AI应用 豆包AI应用下载与安装步骤解析如何下载豆包AI应用 豆包AI应用下载与安装步骤解析如何下载豆包AI应用 豆包AI应用下载与安装步骤解析

    豆包ai应用下载安装方法有三种: 一、手机应用商店搜索“豆包”或“Doubao”,确认开发者为“北京字节跳动科技有限公司”后点击安装; 二、直接使用“豆包AI网页版在线使用入口☜☜☜☜直接进入”; 三、注意常见问题如无法找到应用时检查关键词、安装失败时查看存储和系统版本、iOS用户提示“未受信任的企…

    2026年9月28日 • 用户投稿
    000
  • sublime prettier插件配置_Prettier代码格式化插件配置指南

    sublime prettier插件配置_Prettier代码格式化插件配置指南sublime prettier插件配置_Prettier代码格式化插件配置指南sublime prettier插件配置_Prettier代码格式化插件配置指南sublime prettier插件配置_Prettier代码格式化插件配置指南

    首先安装JsPrettier插件并配置prettier_cli_path和node_path路径,设置format_on_save_enabled为true以实现保存时自动格式化,确保prettier_options与项目规则一致,推荐在项目中本地安装Prettier并通过快捷键Ctrl+Alt+F…

    2026年9月28日 • 用户投稿
    000
  • 将PostgreSQL存储过程转换为Spring Boot原生查询的实践指南

    将PostgreSQL存储过程转换为Spring Boot原生查询的实践指南将PostgreSQL存储过程转换为Spring Boot原生查询的实践指南将PostgreSQL存储过程转换为Spring Boot原生查询的实践指南将PostgreSQL存储过程转换为Spring Boot原生查询的实践指南

    本文旨在指导开发者如何将PostgreSQL存储过程转换为Spring Boot应用中的原生SQL查询。通过分析一个具体的存储过程,我们将详细演示如何构建等效的SQL查询,并介绍Spring Data JPA @Query注解中两种主要的参数映射方式:命名参数和位置参数,以实现存储过程的替代。 存储…

    2026年9月28日 • 用户投稿
    100
  • sublime怎么设置成便携版_Sublime Text创建与使用Portable便携版本

    sublime怎么设置成便携版_Sublime Text创建与使用Portable便携版本sublime怎么设置成便携版_Sublime Text创建与使用Portable便携版本sublime怎么设置成便携版_Sublime Text创建与使用Portable便携版本sublime怎么设置成便携版_Sublime Text创建与使用Portable便携版本

    下载Sublime Text便携版.zip并解压;2. 在解压目录创建Data文件夹;3. 启动sublime_text.exe即进入便携模式,所有配置自动存于Data内;4. 通过复制Data文件夹可实现设置备份与迁移,无需安装或注册表修改,跨设备使用便捷。 Sublime Text 本身不提供官…

    2026年9月28日 • 用户投稿
    000
  • 没有体力限制 没有抽卡的二游!《二重螺旋》10月28日公测

    没有体力限制 没有抽卡的二游!《二重螺旋》10月28日公测没有体力限制 没有抽卡的二游!《二重螺旋》10月28日公测没有体力限制 没有抽卡的二游!《二重螺旋》10月28日公测没有体力限制 没有抽卡的二游!《二重螺旋》10月28日公测

    英雄游戏旗下潘神工作室于8月26日发布消息,其自主研发的免费arpg《二重螺旋》将于10月28日正式上线,登陆pc(epic games商店)、ios及android三大平台。游戏将取消角色与武器的抽卡机制,并彻底移除体力系统。 本作构建在一个魔法与机械交融的世界观中,人类与亚人种共同生活,但拥有双…

    2026年9月28日 • 用户投稿
    000
  • Web无插件RTSP视频流直播系统EasySearcher探测工具无法运行是什么原因?

    Web无插件RTSP视频流直播系统EasySearcher探测工具无法运行是什么原因?Web无插件RTSP视频流直播系统EasySearcher探测工具无法运行是什么原因?Web无插件RTSP视频流直播系统EasySearcher探测工具无法运行是什么原因?Web无插件RTSP视频流直播系统EasySearcher探测工具无法运行是什么原因?

    easynvr分为硬件版本和软件版本,两者的功能基本一致。然而,硬件版本的配置需要额外进行探索和接入步骤才能完成部署。探索功能需要使用tsingsee青犀视频自主研发的easysearcher探测工具,该工具可以在easynvr的官方网站上下载。 在某些情况下,EasySearcher探测工具可能会…

    2026年9月28日 • 用户投稿
    100
  • MySQL怎样使用索引合并优化 复合索引与索引合并策略

    MySQL怎样使用索引合并优化 复合索引与索引合并策略MySQL怎样使用索引合并优化 复合索引与索引合并策略MySQL怎样使用索引合并优化 复合索引与索引合并策略MySQL怎样使用索引合并优化 复合索引与索引合并策略

    索引合并是mysql中一种优化策略,允许在单个查询中使用多个索引来定位数据。其主要类型包括:1. union合并,用于or连接的条件;2. intersection合并,用于and连接的条件;3. sort-union合并,用于需排序后再合并的情况。复合索引与索引合并不同,前者是多列组合索引,后者则…

    2026年9月28日 • 用户投稿
    000
  • 乌鲁木齐银行定向采购 Oracle、IBM、Redhat

    2022年2月18日,乌鲁木齐银行发布《正版oracle软件采购项目》公开询价公告,控制价 283 万元。 采购内容:主要目标为以数量授权模式采购,采购Oracle数据库6C,Oracle weblogic 4C,Oracle集群2C,Oracle ADG 2C。 2022年3月1日发布成交公告,新…

    2026年9月28日
    000
  • 抖音价格保护是什么意思?抖音有价格保护吗

    抖音价格保护是什么意思?抖音有价格保护吗抖音价格保护是什么意思?抖音有价格保护吗抖音价格保护是什么意思?抖音有价格保护吗抖音价格保护是什么意思?抖音有价格保护吗

    随着短视频平台的迅猛发展,抖音早已不只是一个娱乐工具,更成为集内容与电商于一体的综合性平台。越来越多用户选择在抖音购物,但随之而来的问题也引发了关注:刚买完商品会不会马上降价?有没有价格保障机制?今天我们就来深入解析“抖音是否有价格保护”以及“价格保护到底意味着什么”。 一、什么是抖音的价格保护? …

    2026年9月28日 • 用户投稿
    000
  • MBTI测试免费链接入口_ MBTI免费测试网站在线地址

    MBTI测试免费链接入口_ MBTI免费测试网站在线地址MBTI测试免费链接入口_ MBTI免费测试网站在线地址MBTI测试免费链接入口_ MBTI免费测试网站在线地址MBTI测试免费链接入口_ MBTI免费测试网站在线地址

    MBTI测试免费链接入口包括www.16personalities.com和www.16mbti.cn,前者基于荣格理论提供16种人格类型分析,含职业建议;后者支持多次测试、生成多维度报告,具社交分享功能,界面简洁适配多设备,测试约12分钟完成。 MBTI测试免费链接入口在哪里?这是不少网友都关注的…

    2026年9月28日 • 用户投稿
    000
  • 深入理解Java泛型:类型参数与方法重载的实践指南

    深入理解Java泛型:类型参数与方法重载的实践指南深入理解Java泛型:类型参数与方法重载的实践指南深入理解Java泛型:类型参数与方法重载的实践指南深入理解Java泛型:类型参数与方法重载的实践指南

    本文深入探讨了Java泛型中关于类型参数与泛型类实例在方法签名中的区别,以及由此引发的类型不匹配问题。通过一个具体的代码示例,详细解析了为何在泛型方法中,直接传入泛型类实例或其内部类型参数会引发编译错误,并提供了利用方法重载这一核心机制来优雅地解决此类问题的专业指导和示例代码,帮助开发者清晰理解“h…

    2026年9月28日 • 用户投稿
    100
  • 如何用豆包AI写协程代码 协程代码的AI编写技巧大公开

    如何用豆包AI写协程代码 协程代码的AI编写技巧大公开如何用豆包AI写协程代码 协程代码的AI编写技巧大公开如何用豆包AI写协程代码 协程代码的AI编写技巧大公开如何用豆包AI写协程代码 协程代码的AI编写技巧大公开

    用豆包ai写协程代码的关键在于提问方式与后续优化。一、明确所需协程类型,如并发下载或任务管理,提问越具体生成代码越实用;二、注意避免阻塞调用,如将time.sleep改为await asyncio.sleep;三、善用提示词提升代码质量,如指定库、并发数及异常处理;四、结合项目结构调整代码,适配模块…

    2026年9月28日 • 用户投稿
    200
  • 电脑长时间不关机会对硬件造成不可逆损伤吗?

    电脑长时间不关机会对硬件造成不可逆损伤吗?电脑长时间不关机会对硬件造成不可逆损伤吗?电脑长时间不关机会对硬件造成不可逆损伤吗?电脑长时间不关机会对硬件造成不可逆损伤吗?

    长时间不关机不会造成不可逆损伤,但会加速硬件老化。持续运行导致散热系统、机械硬盘、电源电容等部件损耗加剧,尤其是风扇磨损和高温环境下电容老化,影响整体寿命。虽然现代硬件设计成熟,具备保护机制,但长期高温运行仍会缩短CPU、GPU周边元件及SSD写入寿命。相较之下,频繁开关机的热胀冷缩影响较小,适度重…

    2026年9月28日 • 用户投稿
    000
  • 洗碗机普及迎来攻坚战,行业探寻市场爆发“黄金拐点”

    洗碗机普及迎来攻坚战,行业探寻市场爆发“黄金拐点”洗碗机普及迎来攻坚战,行业探寻市场爆发“黄金拐点”洗碗机普及迎来攻坚战,行业探寻市场爆发“黄金拐点”洗碗机普及迎来攻坚战,行业探寻市场爆发“黄金拐点”

    家电行业中,谁是最被看好的“潜力股”之一?洗碗机当之不让。但是现实困境却是,洗碗机渗透率徘徊在4%左右迟迟难以突破,原因何在,又该如何破局? 2025年9月17日,由中国家电网主办的“碗美无菌国补焕新2025中国洗碗机行业高峰论坛”在千年瓷都景德镇拉开帷幕,来自A.O.史密斯、卡萨帝、finish亮…

    2026年9月28日 • 用户投稿
    100
  • 如何用豆包AI生成Python环境配置代码

    如何用豆包AI生成Python环境配置代码如何用豆包AI生成Python环境配置代码如何用豆包AI生成Python环境配置代码如何用豆包AI生成Python环境配置代码

    豆包ai可辅助生成python环境配置代码。1. 首先明确项目需求,如python版本、依赖库和虚拟环境类型;2. 向豆包ai输入具体提示词,获取创建venv和requirements.txt的命令;3. 如需复杂配置,可要求生成开发与生产环境分离的依赖文件;4. 注意版本控制、输出验证及通过多轮交…

    2026年9月28日 • 用户投稿
    100
  • windows8桌面右键新建菜单很卡怎么办_windows8右键菜单卡顿修复方法

    右键菜单卡顿因注册表冗余或软件冲突,需清理ContextMenuHandlers项、删除非New子项、用搜索功能查Directory路径并删多余项,卸载360或NVIDIA等第三方软件,更新显卡蓝牙驱动解决。 如果您在Windows 8桌面上右键点击时,新建菜单响应缓慢或出现卡顿现象,这通常与系统右…

    2026年9月28日
    200

发表回复

登录后才能评论
关注微信