代码之家  ›  专栏  ›  技术社区  ›  canni

如何将此代码转换为非阻塞和无锁代码?

  •  2
  • canni  · 技术社区  · 11 年前

    我有队列,女巫必须有不断增长的缓冲区,这不包括我使用缓冲通道。

    在谷歌搜索之后,我想到了以下代码:

    import (
        "sync"
    )
    
    type Queue struct {
        nodes []interface{}
        head, tail, count int
        lck sync.RWMutex
    }
    
    func (q *Queue) Enqueue(v interface{}) {
        q.lck.Lock()
        defer q.lck.Unlock()
    
        if q.nodes == nil {
            q.nodes = make([]interface{}, 2)
        }
    
        if q.head == q.tail && q.count > 0 {
            nodes := make([]interface{}, len(q.nodes) * 2)
            copy(nodes, q.nodes[q.head:])
            copy(nodes[len(q.nodes) - q.head:], q.nodes[:q.head])
            q.head = 0
            q.tail = len(q.nodes)
            q.nodes = nodes
        }
    
        q.nodes[q.tail] = v
        q.tail = (q.tail + 1) % len(q.nodes)
        q.count++
    }
    
    func (q *Queue) Dequeue() interface{} {
        q.lck.Lock()
        defer q.lck.Unlock()
    
        if len(q.nodes) == 0 {
            return nil
        }
    
        node := q.nodes[q.head]
        q.head = (q.head + 1) % len(q.nodes)
        q.count--
    
        return node
    }
    
    func (q *Queue) Len() int {
        q.lck.RLock()
        defer q.lck.RUnlock()
    
        return q.count
    }
    

    我有没有办法将其转换为非阻塞&无锁队列?

    1 回复  |  直到 11 年前
        1
  •  3
  •   Intermernet    11 年前

    Evan Huus's channels package 提供 ResizableChannel 类型似乎提供了你想要的。

    ResizableChannel在输入和输出之间使用可调整大小的缓冲区实现Channel接口。通道最初的缓冲区大小为1,但可以通过调用Resize()来调整大小。