私はゴリラ/ websocketパッケージのGodocを研究しました。 GolangゴリラWebSocketパッケージの同時実行性を保証する方法
はGodocでは、明らかに同時実行 接続は1つの同時リーダーと1人の同時ライターをサポートすることが述べられています。
アプリケーションは1つ以下のゴルーチンが同時にかつ1個以下ゴルーチンがreadメソッド(NextReader、SetReadDeadline、ReadMessageを呼び出すこと(NextWriter、SetWriteDeadline、WriteMessage、WriteJSON、EnableWriteCompression、SetCompressionLevel)writeメソッドを呼び出すことを保証する責任があります、ReadJSON、SetPongHandler、SetPingHandler)を同時に実行します。
CloseメソッドとWriteControlメソッドは、他のすべての メソッドと並行して呼び出すことができます。
しかし、パッケージによって提供された例の一つで
func (c *Conn) readPump() {
defer func() {
hub.unregister <- c
c.ws.Close()
}()
c.ws.SetReadLimit(maxMessageSize)
c.ws.SetReadDeadline(time.Now().Add(pongWait))
c.ws.SetPongHandler(func(string) error {
c.ws.SetReadDeadline(time.Now().Add(pongWait)); return nil
})
for {
_, message, err := c.ws.ReadMessage()
if err != nil {
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
log.Printf("error: %v", err)
}
break
}
message = bytes.TrimSpace(bytes.Replace(message, newline, space, -1))
hub.broadcast <- message
}
}
このライン
c.ws.SetPongHandler(func(string) error {
c.ws.SetReadDeadline(time.Now().Add(pongWait)); return nil
})
このライン
_, message, err := c.ws.ReadMessage()
はどのようにすべき、最初の行は、それがパッケージ内に作成し、2行目は、さらに重要な
serveWs
を呼び出すゴルーチンで実行されているゴルーチンに呼び出される必要がありますので、コールバック関数があるので、同期していないことのようですI 1つ以上のゴルーチンがSetReadDeadline
,ReadMessage
、SetPongHandler
、SetPingHandler
と同時に呼び出さないようにしてください。
私は上記の関数を呼び出すたびにMutexロックをロックしてロックしようとしますが、その後ロックを解除しますが、すぐに問題が発生します。 forループでReadMessage
が呼び出されるのは普通です(この例でも)。しかしMutextがReadMessage前にロックされている場合、その後、他の読み取り機能がロックを取得することはできませんし、次のメッセージが
この同時実行の問題を扱う上で任意のより良い方法はあり
を受信するまで実行しますか?前もって感謝します。
私が誤読しなかった場合、pingとpongのコールバック関数は実際にReadMessage()が呼び出されるのと同じGoRoutineで実行されます。したがって、この例では並行性が保証されています。また、SetPingHandler()とSetPongHandler()も同期させる必要がありますが、この例ではReadMessage()が呼び出される前に呼び出されるため、問題ありません。 – user7509214