猿问

为什么 gorilla websocket 聊天示例没有发现使用 sync.RWMutex

在聊天示例中有一个名为 hub.go 的文件。


https://github.com/gorilla/websocket/blob/master/examples/chat/hub.go


我对该文件进行了一些更改,它看起来像这样:


type hub struct {

    // Registered connections.

    connections map[int64]*connection


    sync.RWMutex


    // Inbound messages from the connections.

    broadcast chan []byte


    // Register requests from the connections.

    register chan *connection


    // Unregister requests from connections.

    unregister chan *connection

}


var wsHub = hub{

    connections: make(map[int64]*connection),

    broadcast:   make(chan []byte),

    register:    make(chan *connection),

    unregister:  make(chan *connection),

}


func (h *hub) init() {

    for {

        select {

        case c := <-h.register:

            h.Lock()

            h.connections[c.userId] = c

            h.Unlock()

        case c := <-h.unregister:

            h.RLock()

            _, ok := h.connections[c.userId]

            h.RUnlock()

            if ok {

                h.Lock()

                delete(h.connections, c.userId)

                h.Unlock()

                close(c.send)

            }

        case m := <-h.broadcast:

            for _, c := range h.connections {

                select {

                case c.send <- m:

                default:

                    close(c.send)

                    delete(h.connections, c.userId)

                }

            }

        }

    }

}

我已将 sync.RWMutex 添加到集线器结构中,但我不确定这是否有必要。为什么它不包含在示例中?也许我错过了什么?锁定和解锁是不是太过分了?


还有 init() 方法中的最后一种情况,我不确定如何锁定和解锁,因为它同时读取和写入。我应该同时使用 Rlock() 和 Lock() 吗?那会是什么样子?


弑天下
浏览 219回答 1
1回答

慕工程0101907

不需要互斥体,因为单个集线器 goroutine是唯一访问映射的 goroutine。另一种方法是消除 Go 例程和通道,并用使用互斥锁的函数替换它们。type hub struct {&nbsp; connections map[*connection]bool&nbsp; mu sync.Mutex}var h = hub{&nbsp; &nbsp;connections: make(map[*connection]bool),}func (h * hub) register(c *connection) {&nbsp; h.mu.Lock()&nbsp; h.connections[c] = true}func (h *hub) unregister(c *connection) {&nbsp; h.mu.Lock()&nbsp; if _, ok := h.connections[c]; ok {&nbsp; &nbsp; &nbsp;delete(h.connections, c)&nbsp; &nbsp; &nbsp;close(c.send)&nbsp; }&nbsp; h.mu.Unlock()}func (h * hub) broadcast(message []byte) {&nbsp; h.mu.Lock()&nbsp; for c := range h.connections {&nbsp; &nbsp; select {&nbsp; &nbsp; case c.send <- m:&nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; close(c.send)&nbsp; &nbsp; &nbsp; delete(h.connections, c)&nbsp; &nbsp; }&nbsp; }&nbsp; h.mu.Unlock()}保护close(c.send)和c.send <- m使用互斥锁很重要。这可以防止在关闭的通道上发送。
随时随地看视频慕课网APP

相关分类

Go
我要回答