Golang线程安全内存队列实现

在Golang中如何实现一个线程安全的内存队列?需要考虑哪些并发场景?是否有现成的库可以直接使用,还是需要自己实现?如果自己实现的话,使用channel、sync.Mutex还是atomic更合适?性能方面应该如何优化?

2 回复

在Golang中实现线程安全内存队列,推荐以下几种方式:

  1. channel实现(最推荐)
queue := make(chan interface{}, bufferSize)
// 入队
queue <- item
// 出队
item := <-queue
  1. sync.Mutex + slice
type SafeQueue struct {
    mu    sync.Mutex
    items []interface{}
}

func (q *SafeQueue) Enqueue(item interface{}) {
    q.mu.Lock()
    defer q.mu.Unlock()
    q.items = append(q.items, item)
}

func (q *SafeQueue) Dequeue() interface{} {
    q.mu.Lock()
    defer q.mu.Unlock()
    if len(q.items) == 0 {
        return nil
    }
    item := q.items[0]
    q.items = q.items[1:]
    return item
}
  1. container/list + sync.Mutex
type SafeQueue struct {
    mu    sync.Mutex
    list  *list.List
}

func (q *SafeQueue) Enqueue(item interface{}) {
    q.mu.Lock()
    defer q.mu.Unlock()
    q.list.PushBack(item)
}

建议

  • 优先使用channel,这是Go的并发哲学
  • 需要复杂操作时用mutex方案
  • 考虑队列大小,避免内存泄漏
  • 大容量队列建议用ring buffer

简单场景直接用channel,复杂业务逻辑用mutex+slice/list。

更多关于Golang线程安全内存队列实现的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Golang中实现线程安全的内存队列,推荐使用带缓冲的通道(buffered channel)结合互斥锁(mutex)来实现。以下是几种常见实现方式:

1. 基于Channel的简单队列

type SafeQueue struct {
    items chan interface{}
}

func NewSafeQueue(capacity int) *SafeQueue {
    return &SafeQueue{
        items: make(chan interface{}, capacity),
    }
}

// 入队(阻塞)
func (q *SafeQueue) Enqueue(item interface{}) {
    q.items <- item
}

// 出队(阻塞)
func (q *SafeQueue) Dequeue() interface{} {
    return <-q.items
}

// 尝试入队(非阻塞)
func (q *SafeQueue) TryEnqueue(item interface{}) bool {
    select {
    case q.items <- item:
        return true
    default:
        return false
    }
}

// 尝试出队(非阻塞)
func (q *SafeQueue) TryDequeue() (interface{}, bool) {
    select {
    case item := <-q.items:
        return item, true
    default:
        return nil, false
    }
}

// 获取队列长度
func (q *SafeQueue) Len() int {
    return len(q.items)
}

2. 基于Slice和Mutex的队列

type SliceQueue struct {
    items []interface{}
    mutex sync.RWMutex
}

func NewSliceQueue() *SliceQueue {
    return &SliceQueue{
        items: make([]interface{}, 0),
    }
}

func (q *SliceQueue) Enqueue(item interface{}) {
    q.mutex.Lock()
    defer q.mutex.Unlock()
    q.items = append(q.items, item)
}

func (q *SliceQueue) Dequeue() interface{} {
    q.mutex.Lock()
    defer q.mutex.Unlock()
    
    if len(q.items) == 0 {
        return nil
    }
    
    item := q.items[0]
    q.items = q.items[1:]
    return item
}

func (q *SliceQueue) Len() int {
    q.mutex.RLock()
    defer q.mutex.RUnlock()
    return len(q.items)
}

func (q *SliceQueue) IsEmpty() bool {
    return q.Len() == 0
}

3. 环形缓冲区队列

type RingQueue struct {
    items   []interface{}
    head    int
    tail    int
    count   int
    mutex   sync.RWMutex
}

func NewRingQueue(capacity int) *RingQueue {
    return &RingQueue{
        items: make([]interface{}, capacity),
    }
}

func (q *RingQueue) Enqueue(item interface{}) bool {
    q.mutex.Lock()
    defer q.mutex.Unlock()
    
    if q.count == len(q.items) {
        return false // 队列已满
    }
    
    q.items[q.tail] = item
    q.tail = (q.tail + 1) % len(q.items)
    q.count++
    return true
}

func (q *RingQueue) Dequeue() interface{} {
    q.mutex.Lock()
    defer q.mutex.Unlock()
    
    if q.count == 0 {
        return nil
    }
    
    item := q.items[q.head]
    q.items[q.head] = nil // 帮助GC
    q.head = (q.head + 1) % len(q.items)
    q.count--
    return item
}

func (q *RingQueue) Len() int {
    q.mutex.RLock()
    defer q.mutex.RUnlock()
    return q.count
}

使用示例

func main() {
    queue := NewSafeQueue(100)
    
    // 生产者
    go func() {
        for i := 0; i < 10; i++ {
            queue.Enqueue(i)
        }
    }()
    
    // 消费者
    go func() {
        for i := 0; i < 10; i++ {
            item := queue.Dequeue()
            fmt.Println("Dequeued:", item)
        }
    }()
    
    time.Sleep(time.Second)
}

选择建议

  • Channel队列:适合简单的生产者-消费者场景,天然线程安全
  • Slice队列:动态容量,适合不确定队列大小的场景
  • 环形队列:固定容量,内存效率高,适合高性能场景

根据具体需求选择合适的实现方式。

回到顶部