如何在Golang中实现并发安全的队列

来源:我的博客作者:缓存小熊猫头衔:程序员
导读:本期聚焦于小伙伴创作的《如何在Golang中实现并发安全的队列》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《如何在Golang中实现并发安全的队列》有用,将其分享出去将是对创作者最好的鼓励。

在Golang的并发编程场景中,队列是常用的数据结构,用于协调多个goroutine之间的任务传递或数据流转。但原生的切片、链表等队列实现不具备并发安全特性,多个goroutine同时读写时会出现数据错乱、程序崩溃等问题,因此需要实现并发安全的队列。下面介绍几种常见的实现方案。

如何在Golang中实现并发安全的队列

基于sync.Mutex的实现方案

互斥锁是最基础的并发控制手段,通过在队列的入队、出队操作前加锁,操作完成后解锁,保证同一时间只有一个goroutine能修改队列数据,从而实现并发安全。

首先定义队列结构体,包含底层数据切片和互斥锁:

package main

import (
	"fmt"
	"sync"
)

// MutexQueue 基于互斥锁实现的并发安全队列
type MutexQueue struct {
	data []interface{}
	mu   sync.Mutex
}

// NewMutexQueue 初始化队列
func NewMutexQueue() *MutexQueue {
	return &MutexQueue{
		data: make([]interface{}, 0),
	}
}

// Enqueue 入队操作
func (q *MutexQueue) Enqueue(val interface{}) {
	q.mu.Lock()
	defer q.mu.Unlock()
	q.data = append(q.data, val)
}

// Dequeue 出队操作,返回值和是否成功
func (q *MutexQueue) Dequeue() (interface{}, bool) {
	q.mu.Lock()
	defer q.mu.Unlock()
	if len(q.data) == 0 {
		return nil, false
	}
	val := q.data[0]
	q.data = q.data[1:]
	return val, true
}

// Size 获取队列长度
func (q *MutexQueue) Size() int {
	q.mu.Lock()
	defer q.mu.Unlock()
	return len(q.data)
}

这种方案实现简单,适合读写频率相对均衡的场景,但所有操作都需要竞争同一把锁,高并发下锁竞争会比较激烈,性能会有一定损耗。

基于sync.RWMutex的实现方案

如果队列的读操作远多于写操作,可以使用读写锁优化。读写锁允许多个goroutine同时读,但写操作时会独占锁,能减少读场景下的锁竞争。

package main

import (
	"fmt"
	"sync"
)

// RWMutexQueue 基于读写锁实现的并发安全队列
type RWMutexQueue struct {
	data []interface{}
	mu   sync.RWMutex
}

// NewRWMutexQueue 初始化队列
func NewRWMutexQueue() *RWMutexQueue {
	return &RWMutexQueue{
		data: make([]interface{}, 0),
	}
}

// Enqueue 入队操作,写操作加写锁
func (q *RWMutexQueue) Enqueue(val interface{}) {
	q.mu.Lock()
	defer q.mu.Unlock()
	q.data = append(q.data, val)
}

// Dequeue 出队操作,写操作加写锁
func (q *RWMutexQueue) Dequeue() (interface{}, bool) {
	q.mu.Lock()
	defer q.mu.Unlock()
	if len(q.data) == 0 {
		return nil, false
	}
	val := q.data[0]
	q.data = q.data[1:]
	return val, true
}

// Size 获取队列长度,读操作加读锁
func (q *RWMutexQueue) Size() int {
	q.mu.RLock()
	defer q.mu.RUnlock()
	return len(q.data)
}

该方案在读多写少的场景下性能优于互斥锁方案,但如果写操作频率较高,读写锁的开销反而会更大。

基于channel的实现方案

Golang的channel本身就是并发安全的,天生适合用于goroutine之间的通信,也可以直接作为并发安全队列使用。如果队列有固定容量需求,可以初始化带缓冲的channel,超出容量时入队操作会阻塞。

package main

import (
	"fmt"
)

// ChannelQueue 基于channel实现的并发安全队列
type ChannelQueue struct {
	ch chan interface{}
}

// NewChannelQueue 初始化队列,capacity为队列容量,0表示无缓冲
func NewChannelQueue(capacity int) *ChannelQueue {
	return &ChannelQueue{
		ch: make(chan interface{}, capacity),
	}
}

// Enqueue 入队操作,队列满时会阻塞
func (q *ChannelQueue) Enqueue(val interface{}) {
	q.ch <- val
}

// Dequeue 出队操作,队列空时会阻塞,可通过select配合default实现非阻塞出队
func (q *ChannelQueue) Dequeue() (interface{}, bool) {
	val, ok := <-q.ch
	return val, ok
}

// DequeueNonBlock 非阻塞出队
func (q *ChannelQueue) DequeueNonBlock() (interface{}, bool) {
	select {
	case val := <-q.ch:
		return val, true
	default:
		return nil, false
	}
}

// Size 获取队列长度
func (q *ChannelQueue) Size() int {
	return len(q.ch)
}

// Close 关闭队列
func (q *ChannelQueue) Close() {
	close(q.ch)
}

channel方案不需要手动处理锁逻辑,代码更简洁,而且支持和select语句配合实现超时、非阻塞等操作,适合任务传递类的队列场景。但channel不支持直接获取所有元素、遍历等操作,灵活性不如前两种方案。

不同方案对比

以下是三种方案的对比,可根据业务场景选择:

实现方案优点缺点适用场景
sync.Mutex实现简单,逻辑清晰锁竞争激烈时性能差读写频率均衡的通用场景
sync.RWMutex读多写少时性能更好写频繁时开销更大读操作远多于写操作的场景
channel原生并发安全,支持阻塞/非阻塞操作灵活性低,不支持遍历等操作goroutine间任务传递场景

注意事项

  • 使用互斥锁或读写锁方案时,要注意锁的粒度,尽量只锁队列数据修改的部分,避免锁范围过大影响性能。
  • 使用channel方案时,如果队列不再使用,要及时调用close方法关闭channel,避免goroutine泄漏。
  • 出队操作要判断返回值的有效性,避免队列为空时获取到无效数据导致程序异常。

Golang并发安全队列goroutinesync_mutexchannel修改时间:2026-06-24 21:27:33

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。