1

Redigo 是 redis 数据库的 golang 客户端。它使用 structPool来维护一个连接池。这个结构持有一个互斥锁,用于应用程序并行放置和获取连接。

type Pool struct {
    // ...
    IdleTimeout time.Duration
    mu     sync.Mutex
    // Stack of idleConn with most recently used at the front.
    idle list.List
}

在其get方法中,连接池首先删除过时的(空闲超时)连接。当发现一个过时的连接时,池将其弹出,释放锁,然后关闭连接,再次尝试获取锁。

func (p *Pool) get() (Conn, error) {
    p.mu.Lock()

    // Prune stale connections.

    if timeout := p.IdleTimeout; timeout > 0 {
        for i, n := 0, p.idle.Len(); i < n; i++ {
            e := p.idle.Back()
            if e == nil {
                break
            }
            ic := e.Value.(idleConn)
                if ic.t.Add(timeout).After(nowFunc()) {
                    break
                }
            p.idle.Remove(e)
            p.release()
            // Why does pool unlock and try to acquire lock again?
            p.mu.Unlock()
            // Close this stale connection.
            ic.c.Close()
            p.mu.Lock()
        }
    }

为什么池解锁并尝试再次获取锁,而不是在函数返回之前解锁?我想关闭一个连接可能会花费很多时间,这会减慢等待这个互斥锁的其他 goroutine。

这是整个Pool get 方法

4

1 回答 1

0

关闭一个连接可能会花费很多时间,这会减慢等待这个互斥体的其他 goroutine。正如@Cerise Limón 所说 - 这次锁定所有池的使用似乎是不明智的。

解锁互斥锁后,等待的 goroutine 之一获得互斥锁。虽然 goroutine forget方法仍然需要移除陈旧的连接,但 forput方法可以将连接放入池中,并尽快继续做其他工作。

于 2017-03-13T02:22:41.303 回答