1 回答
TA贡献1802条经验 获得超4个赞
总结我的评论作为答案:
当您写入客户端时,您从 GlassFish 消息中获取 clientId,从地图中获取客户端,然后写入它 - 基本上是clients[clientId].WriteMessage(...)。
虽然您的地图访问可以是线程安全的,但写入不是,因为这可以被视为:
// map access - can be safe if you're using a concurrent map
client := clients[clientId]
// writing to a client, not protected at all
client.WriteMessage(...)
所以可能发生的事情是两个单独的 goroutine 同时写入同一个客户端。您应该通过在WriteMessage方法实现中添加互斥锁来保护您的客户端免受它的影响。
顺便说一句,实际上不是使用互斥锁来保护此方法,而是使用一个通道来编写消息,并且每个客户端使用一个 goroutine 从通道中消费并写入实际套接字,而不是使用互斥锁来保护此方法。
所以在客户端结构中我会做这样的事情:
type message struct {
msgtype string
msg string
}
type client struct {
...
msgqueue chan *message
}
func (c *client)WriteMessage(messageType, messageText string) {
// I'm simplifying here, but you get the idea
c.msgqueue <- &message{msgtype: messageType, msg: messageText}
}
func (c *client)writeLoop() {
go func() {
for msg := ragne c.msgqueue {
c.actuallyWriteMessage(msg)
}
}()
}
并且在创建新的客户端实例时,只需启动写入循环
- 1 回答
- 0 关注
- 388 浏览
添加回答
举报