Golang线程安全内存队列实现
在Golang中如何实现一个线程安全的内存队列?需要考虑哪些并发场景?是否有现成的库可以直接使用,还是需要自己实现?如果自己实现的话,使用channel、sync.Mutex还是atomic更合适?性能方面应该如何优化?
2 回复
在Golang中实现线程安全内存队列,推荐以下几种方式:
- channel实现(最推荐)
queue := make(chan interface{}, bufferSize)
// 入队
queue <- item
// 出队
item := <-queue
- 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
}
- 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队列:动态容量,适合不确定队列大小的场景
- 环形队列:固定容量,内存效率高,适合高性能场景
根据具体需求选择合适的实现方式。

