多协程同步模型

在Go程序启动时,指定了多核多线程运行模式下,每个协程都可能被投递到不同的线程上被执行。
类似多线程编程,需要考虑访问互斥资源的问题。
常见的,会使用互斥锁等机制,来处理这类问题。Go语言也是支持的。
同时,Go语言提供了chan机制,也就是上图中所画的模型。
这种同步模型的好处有:
- 相关的逻辑都在1根主协程中执行,从而把相关逻辑变成了同步编程。
- 其他协程通过chan,类似投递消息的方式,与主协程互动。即不直接操纵互斥资源,从而避免了访问互斥问题。
此外,与一些常见的游戏框架比,一些游戏框架会把所有业务逻辑串行执行。
而这种模型,则是把1个房间内的游戏逻辑串行化。从而使所有房间的游戏逻辑并行执行。这样可以更好的利用CPU了
项目代码示例分析 - chan_PlayerCmd
上一节中的 加入房间、销毁房间,都是用过chan的方式告知房间主循环,并在房间主循环内实现了玩家加入房间、房间销毁操作。
这里再举个例子,巩固下。
我们来看下RoomServer,从收到玩家消息,经过 chan(chan_PlayerCmd),到房间主循环执行的过程
收到玩家消息
func (this *PlayerTask) ParseMsg(data []byte, flag byte) bool { // ... (无关代码略) switch cmd { default: this.room.PostPlayerCmd(this.id, cmd, data, flag) } return true }PostPlayerCmd函数
func (this *Room) PostPlayerCmd(playerID uint64, cmd usercmd.MsgTypeCmd, data []byte, flag byte) { playerCmd := &PlayerCmd{playerID: playerID, cmd: cmd, flag: flag} // Must copy data. playerCmd.data = make([]byte, len(data)) copy(playerCmd.data, data) this.chan_PlayerCmd <- playerCmd }最后一行,把消息投递给了chan_PlayerCmd
房间主循环执行chan_PlayerCmd投递来的消息
func (this *Room) Loop() { // ... (无关代码略) for { select { // ... (无关代码略) case op := <-this.chan_PlayerCmd: if !this.IsClosed() { player, ok := this.Players[op.playerID] if ok { player.OnRecvPlayerCmd(op.playerID, op.cmd, op.data, op.flag) } else { glog.Info("chan_PlayerCmd:no player,", op.playerID, " cmd:", op.cmd) } } // ... (无关代码略) } } }player.OnRecvPlayerCmd 函数内根据消息内容,实现分别处理
以上