golang并发编程模型之actor(一)

前言
多线程/进程编程是每个程序员的基本功,同时也是开发中的难点,处理各种“锁”的问题是让人十分头痛的一件事。
Actor模型,在1973由Carl Hewitt定义,被Erlang OTP推广,其消息传递更加符合面向对象的原始意图。Actor模型属于并发组件模型,通过组件方式定义并发编程范式的高级阶段,避免使用者直接接触多线程并发或线程池等基础概念。
Actor模型的基础就是消息传递,一个Actor模型可以认为是一个基本的计算单元,它能接收消息并基于消息执行运算,也可以发送消息给其他Actor模型。各个Actor模型之间相互隔离,不共享内存。
Actor模型本身封装了状态和行为,在进行并发编程时,Actor模型只需要关注消息和其本身。而消息是一个不可变对象,所以Actor模型不需要去关注锁和内存原子性等一系列多线程常见的问题。

1:上代码
在这里插入图片描述
核心代码
MySynMsgChan 同步时使用

package myqueueimport ("gameserver/myqueue/queue/mpsc""runtime""sync/atomic""log""time"
)const (idle int32 = iotarunning
)// //
type Dispatcher interface {Schedule(fn func())Throughput() int
}type goroutineDispatcher intfunc (goroutineDispatcher) Schedule(fn func()) {go fn()
}func (d goroutineDispatcher) Throughput() int {return int(d)
}func NewDefaultDispatcher(throughput int) Dispatcher {return goroutineDispatcher(throughput)
}type synchronizedDispatcher intfunc (synchronizedDispatcher) Schedule(fn func()) {fn()
}func (d synchronizedDispatcher) Throughput() int {return int(d)
}func NewSynchronizedDispatcher(throughput int) Dispatcher {return synchronizedDispatcher(throughput)
}/type Statistics interface {MessageReceived(message interface{})
}type MyQueue struct {userMailbox     *mpsc.QueueschedulerStatus int32userMessages    int32suspended       booldispatcher      DispatchermailboxStats    []StatisticsbStop           bool
}func (m *MyQueue) PostUserMessage(message interface{}) {if m.isStop() {return}//	for _, ms := range m.mailboxStats {//		ms.MessagePosted(message)//	}m.userMailbox.Push(message)atomic.AddInt32(&m.userMessages, 1)//m.schedule()if atomic.CompareAndSwapInt32(&m.schedulerStatus, idle, running) {m.dispatcher.Schedule(m.processMessages)}
}func (m *MyQueue) processMessages() {process:m.run()// set mailbox to idleatomic.StoreInt32(&m.schedulerStatus, idle)user := atomic.LoadInt32(&m.userMessages)// check if there are still messages to process (sent after the message loop ended)if user > 0 {// try setting the mailbox back to runningif atomic.CompareAndSwapInt32(&m.schedulerStatus, idle, running) {//	fmt.Printf("looping %v %v %v\n", sys, user, m.suspended)goto process}}}func (m *MyQueue) run() {var msg interface{}//	var bok booldefer func() {if r := recover(); r != nil {log.Printf("(m *MyQueue) run() err=%v  msg=%#v \n", r, msg)}}()i, t := 0, m.dispatcher.Throughput()for {if i > t {i = 0runtime.Gosched()}i++if msg = m.userMailbox.Pop(); msg != nil {atomic.AddInt32(&m.userMessages, -1)if len(m.mailboxStats) > 0 && m.mailboxStats[0] != nil {m.mailboxStats[0].MessageReceived(msg)}} else {return}}
}func (m *MyQueue) Stop() {if !m.bStop {m.bStop = true}
}// 
func (m *MyQueue) isStop() bool {return m.bStop
}func UnboundedMyQueue(dispatcher Dispatcher, mailboxStats ...Statistics) *MyQueue {return &MyQueue{userMailbox:  mpsc.New(),mailboxStats: mailboxStats,dispatcher:   dispatcher,}
}type MySynMsgChan struct {MsgData   interface{}MsgChan   chan interface{}ChanState *int32
}func GenerateMySynMsg(data interface{}) *MySynMsgChan {chanState := new(int32)*chanState = 1return &MySynMsgChan{data, make(chan interface{}, 1), chanState}
}func (self *MySynMsgChan) WaitSynReply(d time.Duration) (interface{}, bool) {if d < time.Millisecond {d = time.Millisecond}timetick := time.NewTimer(d)for {select {case <-timetick.C:atomic.StoreInt32(self.ChanState, 0)return nil, falsecase msg, ok := <-self.MsgChan:atomic.StoreInt32(self.ChanState, 0)timetick.Reset(0)if ok {return msg, true}}}return nil, false
}

使用也很简单
实现 MessageReceived 接口

func CeateUserActor(ws *websocket.Conn, wsIndex uint32, accname, headrul string, platformId, serverid uint32) {useractor := new(UserActor)useractor.WsConn = wsuseractor.shareUserState = new(shr.ShareState)useractor.shareUserState.State = 1useractor.remoteip = RetmoteIp(ws.RemoteAddr().String())......................................................useractor.wsConnIndex = wsIndexuseractor.u32State = STATE_READY_RECV_LOGINuseractor.CurMaxItemID = base.ITEM_ID_MIN_NUM //默认开始值useractor.CurMaxHeroID = base.HERO_ID_MIN_NUM //默认开始值useractor.msgQue = myqueue.UnboundedMyQueue(myqueue.NewDefaultDispatcher(64), useractor)useractor.commonBagItemMap = map[uint64]uint64{}useractor.endTimeItemMap = treemap.NewWith(treeutils.UInt64Comparator)useractor.msgQue.PostUserMessage(&shr.NewSessionQueryUserInfo{})SetUpRecv(ws, useractor.msgQue, wsIndex, accname, serverid)
}
..........................
func (self *UserActor) MessageReceived(r interface{}) {if self.u32State == STATE_CLOSE {return}switch r.(type) {case *shr.NewSessionQueryUserInfo: //新连接查询self.doNewSessionQueryPlayer()case *shr.ClientRecvNetMsg: //protobufif !self.doClienNetData(r.(*shr.ClientRecvNetMsg).Clientdata) {self.doDisconnect(self.wsConnIndex)}case *shr.NetDisconnect: //网络断开dis := r.(*shr.NetDisconnect)self.doDisconnect(dis.DisIndex)...................................................
}//
..........................发送消息 会放入mailbox里
func SendMsgToAccMgr(v interface{}) {*****.msgque.PostUserMessage(v)
}

同步等待回复
在这里插入图片描述

2:测试,这个已经在项目上用过了,这里不专门再写DEMO测试

3:如果觉得有用,麻烦点个赞,加个收藏

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

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

相关文章

Android13 允许桌面自动旋转

一&#xff09;需求-场景 Android13 实现允许桌面自动旋转 Android13 版本开始后&#xff0c;支持屏幕自动旋转&#xff0c;优化体验和兼容性&#xff0c;适配不同屏幕 主界面可自动旋转 二&#xff09;参考资料 android framework13-launcher3【06手机旋转问题】 Launcher默…

vue2:el-select中的@change事件如何传入自定义参数

在 Element UI 中,el-select 组件用于创建一个下拉选择框。当选项发生变化时,你可以使用 @change 事件来监听这个变化。默认传入的是选中项的值(如果是多选,则传入一个数组) 但是有些时候需要传入额外的自定义参数,可以通过如下方式实现 1、template中定义事件响应函数时…

Go 1.19.4 HTTP编程-Day 20

1. HTTP协议 1.1 基本介绍 HTTP协议又称超文本传输协议&#xff0c;属于应用层协议&#xff0c;在传输层使用TCP协议。HTTP协议属是无状态的&#xff0c;对事务处理没有记忆能力&#xff0c;如果需要保存状态需要引用其他技术&#xff0c;如Cookie。HTTP协议属是无连接的&…

Tomcat使用教程

下载地址&#xff1a;https://tomcat.apache.org/ 配置环境变量 变量名: CATALINA_HOME 变量值: D:\tools\apache-tomcat-9.0.97 Path: %CATALINA_HOME%\bin 启动Tomcat(打开命令提示符) startup.bat 解决乱码问题(打开conf\logging.properties) java.util.logging.Conso…

WPF+LibVLC开发播放器-LibVLC在C#中的使用

LibVLC在C#中的使用 安装包Nuget使用控件使用播放器初始化加载视频文件 视频教程&#xff1a; 使用WPFLibVLC快速开发一个播放器 安装包Nuget 安装下面两个包,必须安装两个 一个是相关框架对应的包&#xff0c;Winform就安装LibVLCSharp.Winform;WPF就安装LibVLCSharp.WPF&am…

[创业之路-173]:《BLM战略规划》- 战略洞察 (战略能力中最最核心的能力) - 市场洞察 -3- 看竞争对手-要比你的竞争对手跟了解他们自己

目录 一、五看三定 二、看竞争 2.1 概述 1、分析竞争对手 2、进行价值链分析 3、紧盯标杆对手 4、关注新进入者和替代产品 5、制定竞争策略 2.2 看竞争的主要内容&#xff1a;背景信息、战略、价值定位、价值链、价值交付、组织架构、财务绩效 1、背景信息 2、战略 …

Mysql - 存储引擎

一 MYSQL体系结构简介 MYSQL的体系结构可以分为四个层级&#xff0c;从上往下依次为&#xff1a; 1. 连接层: 最上层为客户端以及一些连接服务&#xff0c;包含连接操作&#xff0c;例如JAVA想要与MYSQL建立连接就需要用到JDBC&#xff0c;PHP语言与Python也可以连接到MYSQL&am…

基于MinIO打造高可靠分布式“本地”文件系统

MinIO是一款高性能的对象存储服务&#xff0c;而S3协议是由亚马逊Web服务&#xff08;AWS&#xff09;制定的一种标准协议&#xff0c;用于云存储服务之间的数据交换。MinIO与S3协议的关系在于&#xff0c;MinIO实现了S3协议的接口&#xff0c;这意味着用户可以使用与AWS S3相同…

电子应用设计方案-43:智能手机充电器系统方案设计

智能手机充电器系统方案设计 一、引言 随着智能手机的广泛应用&#xff0c;对充电器的性能、效率和安全性提出了更高的要求。本方案旨在设计一款高效、安全、兼容多种快充协议的智能手机充电器。 二、系统概述 1. 系统目标 - 提供快速、稳定、安全的充电功能。 - 兼容主流的智…

vue3项目最新eslint9+prettier+husky+stylelint+vscode配置

一、eslint9和prettier通用配置 安装必装插件 ESlint9.x pnpm add eslintlatest -DESlint配置 vue 规则 , typescript解析器 pnpm add eslint-plugin-vue typescript-eslint -DESlint配置 JavaScript 规则 pnpm add eslint/js -D配置所有全局变量 globals pnpm add globa…

【环境搭建】WordPress本地部署搭建及历史版本插件安装(windows系统)

&#x1f3d8;️个人主页&#xff1a; 点燃银河尽头的篝火(●’◡’●) 如果文章有帮到你的话记得点赞&#x1f44d;收藏&#x1f497;支持一下哦 【环境搭建】WordPress本地部署搭建及历史版本插件安装&#xff08;windows系统&#xff09; WordPress搭建环境部署&#xff08;…

qt QTemporaryFile详解

1、概述 QTemporaryFile类是Qt框架中用于创建和管理临时文件的类。它提供了一个安全且便捷的方式来生成唯一的临时文件&#xff0c;这些文件通常用于存储临时数据&#xff0c;如缓存、草稿或中间结果。QTemporaryFile确保了临时文件的唯一性&#xff0c;避免了文件名冲突&…

Gitee配置以及如何将本地项目提交到远程仓库

文章目录 准备远程仓库配置注册新建仓库 配置git 生成ssh&#xff0c;输入以下命令&#xff0c;然后连敲三次回车键配置公钥本地代码上传 准备 1.本地下载git 2.注册远程仓库账号 远程仓库配置 注册 官网&#xff1a;https://gitee.com 完成注册 新建仓库 头像->设置-…

基于Java和Vue开发的漫画阅读软件漫画阅读小程序漫画APP

前景分析 受众广泛&#xff1a;漫画的受众群体广泛&#xff0c;不仅限于青少年&#xff0c;还涵盖了成年人等多个年龄层和社会阶层。漫画文化在全球范围内的影响力不断扩大&#xff0c;未来漫画软件创业可以考虑全球市场的拓展。 市场需求大&#xff1a;数字化阅读趋势下&…

2024.12.2——[极客大挑战 2019]Secret File 1

知识点&#xff1a;抓包 代码审计 filter伪协议 一、解题步骤 step 1 查看源代码中的信息 查看源代码发现一个php文件&#xff1a;[./Archive_room.php](http://72df1f22-85bf-47bb-b23a-efcaf88701d4.node5.buuoj.cn:81/Archive_room.php) 点进去后发现没什么用&#xff0c…

距离与AoA辅助的三维测距算法,适用于自适应基站数量的情况。订阅专栏后可直接查看完整源代码

本MATLAB 代码实现了一个基于距离与到达角(AoA)的三维测距系统,主要用于在动态环境中估计目标物体的位置。提供本算法与仅侧角(AoA)的定位误差对比 文章目录 代码运行结果源代码代码功能概述主要步骤分析初始化部分AOA定位绘图部分输出部分代码的应用和意义总结代码运行结…

[241206] X-CMD 发布 v0.4.15:env 升级,mirror 支持华为/腾讯 npm 镜像,pb-wayland 剪贴板

目录 X-CMD 发布 v0.4.15&#x1f4c3;Changelog&#x1f4e6; env|pkg&#x1fa9e; mirror&#x1f4d1; pb&#x1f3a8; theme|starship|ohmyposh&#x1f916; chat&#x1f4dd; man✅ 升级指南 X-CMD 发布 v0.4.15 &#x1f4c3;Changelog &#x1f4e6; env|pkg 新增…

Python办公—DataMatrix二维条码制作

目录 专栏导读1、库的介绍2、库的安装3、核心代码4、完整代码总结专栏导读 🌸 欢迎来到Python办公自动化专栏—Python处理办公问题,解放您的双手 🏳️‍🌈 博客主页:请点击——> 一晌小贪欢的博客主页求关注 👍 该系列文章专栏:请点击——>Python办公自动化专…

Webpack Tree Shaking 技术原理及应用实战,优化代码,精简产物

前言 在前端开发中&#xff0c;优化代码体积和提升应用性能是至关重要的课题。Webpack 提供了多种优化手段来帮助开发者实现这一目标&#xff0c;Tree Shaking 就是其中一种非常重要的优化技术&#xff0c;它通过在编译阶段移除未被使用的代码模块&#xff0c;从而显著减小最终…

『RabbitMQ』 windows下 安装RabbitMQ 并在Python中使用测试

目录 1. 安装ERLANG2. 安装RabbitMQ3. 新建用户Python的测试代码 生产者和消费者总结欢迎关注 『RabbitMQ』 专栏,持续更新中 欢迎关注 『RabbitMQ』 专栏,持续更新中 1. 安装ERLANG 下载之前先看兼容性,这里我打算下载26.1版本的Erlang以适配RabbitMQ cloud.emqx.com/cons…